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.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Dawn; using GameNetcodeStuff; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; using UnityEngine.SceneManagement; using Y4NGZMonsters.Shared; using Y4NGZScissorsCreature.NetcodePatcher; [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("Y4NGZScissorsCreature")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+25ca94fed298fe073d4c739917e3b7f046e875bf")] [assembly: AssemblyProduct("Y4NGZScissorsCreature")] [assembly: AssemblyTitle("Y4NGZScissorsCreature")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] 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 Y4NGZScissorsCreature { public sealed class ScissorsCreatureAI : EnemyAI { public const int StateIdleWalk = 0; public const int StateWindupWalk = 1; public const int StateRushSnipping = 2; [Header("Scissors Creature anchors")] public Transform attackOrigin; public Transform wheelBone; public Collider bodyBlockerCollider; [Header("Scissors Creature audio")] public AudioClip windupClip; public AudioClip wheelUnwindClip; public AudioClip attackedByPlayerClip; public AudioClip footstepClip; public AudioClip attackRunClip; public AudioClip tickingClip; public AudioClip alarmClip; public AudioClip idleGrowlClip; public AudioClip snipKillClip; public AudioClip[] snipClips; public AudioSource tickingAudioSource; public AudioSource alarmAudioSource; private const float ScissorsDamageBehindOrigin = 1.1f; private const float ScissorsDamageAheadOfOrigin = 2.75f; private const float ScissorsDamageHalfWidth = 1.35f; private const float ScissorsDamageBelowOrigin = 0.75f; private const float ScissorsDamageAboveOrigin = 1.35f; private const float ScissorsApproachDistance = 2.35f; private const float ScissorsRushStoppingDistance = 0.6f; private const int ScissorsHittableForce = 2; private const float SnipjackDoorwayAgentRadius = 0.32f; private const float ScissorsNavigationRadius = 0.32f; private const float ScissorsIdleStoppingDistance = 0.85f; private const float ScissorsProgressSpeedFraction = 0.25f; private const float ScissorsStuckRecoverySeconds = 1.2f; private const float ScissorsOffMeshRepairInterval = 0.8f; private const float WheelConnectorRadius = 0.055f; private const float HeadTrackYawGeometryLimit = 45f; private const float HeadTrackPitchGeometryLimit = 30f; private const float HeadTrackAbandonYawDegrees = 100f; private const float HeadTrackSearchInterval = 0.25f; private const float HeadTrackDeadZoneDegrees = 0.4f; private static readonly Vector3 WheelFallbackLocalPosition = new Vector3(0f, 1.18f, -0.55f); private static readonly Vector3 WheelConnectorBodyAnchorLocalPosition = new Vector3(0f, 1.18f, -0.12f); private const string ScanSubTextIdle = "Try unwinding the back wheel"; private const string ScanSubTextWound = "Try unwinding the back wheel"; private readonly RaycastHit[] _lineOfSightHits = (RaycastHit[])(object)new RaycastHit[32]; private readonly Collider[] _attackOverlapResults = (Collider[])(object)new Collider[64]; private readonly Dictionary _lastDamageTimes = new Dictionary(); private readonly Dictionary _lastHittableDamageTimes = new Dictionary(); private float _windupTimer; private float _snipAudioTimer; private float _footstepAudioTimer; private float _idleGrowlTimer; private int _tickingRepeatCount; private Vector3 _lastKnownTargetPosition; private float _lastTargetContactTime; private float _currentTargetLastContactTime; private Transform _wheelInteractionProxy; private Transform _wheelConnector; private Quaternion _wheelBaseLocalRotation = Quaternion.identity; private float _wheelVisualAngle; private ScanNodeProperties _creatureScanNode; private bool _scanNodeShowsWheelHint; private Vector3 _lastNavigationRecoveryPosition; private float _navigationStuckTimer; private float _nextAgentRepairTime; private bool _capturedWheelBase; private bool _windupTickingActive; private Transform _headTrackBone; private bool _headTrackCalibrated; private Quaternion _headTrackBaseLocalRotation = Quaternion.identity; private Vector3 _headTrackFaceLocalAxis = Vector3.forward; private float _headTrackYawDegrees; private float _headTrackPitchDegrees; private float _nextHeadTrackSearchTime; private PlayerControllerB _headTrackTarget; public bool CanUseWindupWheel { get { if (!base.isEnemyDead) { if (base.currentBehaviourStateIndex != 1) { return base.currentBehaviourStateIndex == 2; } return true; } return false; } } private float WalkSpeed { get { if (Plugin.ModConfig == null) { return 0.286f; } return Plugin.ModConfig.WalkSpeed.Value; } } private float WindupMoveSpeed => 0.05f; private float WalkTurnSpeed => 11.7f; private float RushSpeed { get { if (Plugin.ModConfig == null) { return 6.24f; } return Plugin.ModConfig.RushSpeed.Value; } } private float DetectionRange { get { if (Plugin.ModConfig == null) { return 28f; } return Plugin.ModConfig.DetectionRange.Value; } } private float DetectionWidth => 75f; private float ProximityAwareness => 4f; private float WindupDuration { get { if (Plugin.ModConfig == null) { return 12f; } return Plugin.ModConfig.WindupDuration.Value; } } private float AttackDamageCooldown => 0.45f; private int AttackDamage { get { if (Plugin.ModConfig == null) { return 35; } return Plugin.ModConfig.AttackDamage.Value; } } private float WheelInteractDistance => 3f; private float DisengageDistance => 20f; private float LostContactGracePeriod => 7f; private float RushSearchTimeout => 8f; private bool HeadTrackingEnabled => true; private float HeadTrackingRange => 18f; private float HeadTrackingMaxYaw => Mathf.Clamp(22f, 0f, 45f); private float HeadTrackingMaxPitch => Mathf.Clamp(12f, 0f, 30f); private float HeadTrackingTurnSpeed => 90f; public override void Awake() { try { ((EnemyAI)this).Awake(); ResolveRuntimeReferences(); } catch (Exception arg) { Plugin.Log.LogError((object)$"[ScissorsCreatureAI] Awake failed: {arg}"); } } public override void Start() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) try { ((EnemyAI)this).Start(); Plugin.EnsureScanNode(((Component)this).gameObject); ResolveRuntimeReferences(); _idleGrowlTimer = Random.Range(2f, 6f); ConfigureAgentForState(0); _lastNavigationRecoveryPosition = ((Component)this).transform.position; if ((Object)(object)base.creatureAnimator != (Object)null) { base.creatureAnimator.applyRootMotion = false; base.creatureAnimator.SetTrigger("DoIdleWalk"); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[ScissorsCreatureAI] Start failed: {arg}"); } } public override void Update() { try { ((EnemyAI)this).Update(); TickScanNodeSubText(); if (!base.isEnemyDead && !((Object)(object)StartOfRound.Instance == (Object)null) && !StartOfRound.Instance.allPlayersDead) { if ((Object)(object)base.creatureAnimator != (Object)null) { base.creatureAnimator.applyRootMotion = false; } if (((NetworkBehaviour)this).IsServer) { TickServerState(Time.deltaTime); RepairAgentIfNeeded(); TickNavigationRecovery(Time.deltaTime); } TickFootstepAudio(Time.deltaTime); TickWindupTickingAudio(); TickAttackAlarmAudio(); TickSnipAudio(Time.deltaTime); TickIdleGrowlAudio(Time.deltaTime); DamageObjectsInAttackVolume(); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[ScissorsCreatureAI] Update failed: {arg}"); } } private void LateUpdate() { try { if (!base.isEnemyDead) { TickWheelVisual(Time.deltaTime); } AlignWheelTargetsAndConnector(); TickHeadTracking(Time.deltaTime); } catch (Exception arg) { Plugin.Log.LogError((object)$"[ScissorsCreatureAI] LateUpdate failed: {arg}"); } } private void TickHeadTracking(float deltaTime) { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: 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) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_005d: 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) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) //IL_01d1: 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_01dd: 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_01ed: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_headTrackBone == (Object)null || !HeadTrackingEnabled || !CalibrateHeadTracking()) { return; } float num = 0f; float num2 = 0f; if (!base.isEnemyDead && TryGetHeadTrackFocusPoint(out var focusPoint)) { Vector3 val = focusPoint - _headTrackBone.position; Vector3 val2 = ((Component)this).transform.InverseTransformDirection(val); if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { ((Vector3)(ref val2)).Normalize(); float num3 = Mathf.Atan2(val2.x, val2.z) * 57.29578f; float num4 = (0f - Mathf.Asin(Mathf.Clamp(val2.y, -1f, 1f))) * 57.29578f; if (Mathf.Abs(num3) <= 100f) { num = Mathf.Clamp(num3, 0f - HeadTrackingMaxYaw, HeadTrackingMaxYaw); num2 = Mathf.Clamp(num4, 0f - HeadTrackingMaxPitch, HeadTrackingMaxPitch); } } } float num5 = HeadTrackingTurnSpeed * deltaTime; float num6 = HeadTrackingTurnSpeed * 0.6f * deltaTime; _headTrackYawDegrees = Mathf.MoveTowards(_headTrackYawDegrees, num, num5); _headTrackPitchDegrees = Mathf.MoveTowards(_headTrackPitchDegrees, num2, num6); _headTrackBone.localRotation = _headTrackBaseLocalRotation; if (!(Mathf.Abs(_headTrackYawDegrees) < 0.4f) || !(Mathf.Abs(_headTrackPitchDegrees) < 0.4f)) { Quaternion val3 = Quaternion.Euler(_headTrackPitchDegrees, _headTrackYawDegrees, 0f); Vector3 val4 = ((Component)this).transform.TransformDirection(val3 * Vector3.forward); Vector3 val5 = _headTrackBone.TransformDirection(_headTrackFaceLocalAxis); if (!(((Vector3)(ref val4)).sqrMagnitude < 0.0001f) && !(((Vector3)(ref val5)).sqrMagnitude < 0.0001f)) { _headTrackBone.rotation = Quaternion.FromToRotation(((Vector3)(ref val5)).normalized, ((Vector3)(ref val4)).normalized) * _headTrackBone.rotation; } } } private bool CalibrateHeadTracking() { //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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0051: 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 (_headTrackCalibrated) { return true; } if ((Object)(object)_headTrackBone == (Object)null) { return false; } _headTrackBaseLocalRotation = _headTrackBone.localRotation; Vector3 val = _headTrackBone.InverseTransformDirection(((Component)this).transform.forward); _headTrackFaceLocalAxis = ((((Vector3)(ref val)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val)).normalized : Vector3.forward); _headTrackCalibrated = true; return true; } private bool TryGetHeadTrackFocusPoint(out Vector3 focusPoint) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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) focusPoint = Vector3.zero; PlayerControllerB val = base.targetPlayer; if ((Object)(object)val == (Object)null || val.isPlayerDead || !((EnemyAI)this).PlayerIsTargetable(val, false, false, true)) { if (Time.time >= _nextHeadTrackSearchTime) { _nextHeadTrackSearchTime = Time.time + 0.25f; _headTrackTarget = FindClosestVisibleTargetablePlayer(HeadTrackingRange); } val = _headTrackTarget; } if ((Object)(object)val == (Object)null || val.isPlayerDead || !((EnemyAI)this).PlayerIsTargetable(val, false, false, true)) { _headTrackTarget = null; return false; } Transform val2 = (((Object)(object)val.gameplayCamera != (Object)null) ? ((Component)val.gameplayCamera).transform : ((Component)val).transform); if (Vector3.Distance(_headTrackBone.position, val2.position) > HeadTrackingRange) { return false; } focusPoint = val2.position; return true; } public override void DoAIInterval() { try { ((EnemyAI)this).DoAIInterval(); if (((NetworkBehaviour)this).IsServer && !base.isEnemyDead && !((Object)(object)StartOfRound.Instance == (Object)null) && !StartOfRound.Instance.allPlayersDead) { switch (base.currentBehaviourStateIndex) { case 0: DoIdleWalk(); break; case 1: DoWindupWalk(); break; case 2: DoRushSnipping(); break; } } } catch (Exception arg) { Plugin.Log.LogError((object)$"[ScissorsCreatureAI] DoAIInterval failed: {arg}"); } } private void TickServerState(float deltaTime) { switch (base.currentBehaviourStateIndex) { case 1: _windupTimer += deltaTime; ConfigureAgentForState(1); if (_windupTimer >= WindupDuration) { if (CanBeginRushSnipping()) { BeginRushSnipping(); } else { WindDownToIdle(); } } break; case 2: ConfigureAgentForState(2); break; } } private void DoIdleWalk() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) ConfigureAgentForState(0); if (!base.currentSearch.inProgress) { ((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null); } PlayerControllerB val = FindClosestVisibleTargetablePlayer(DetectionRange); if ((Object)(object)val != (Object)null) { BeginWindup(val); } } private void DoWindupWalk() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) bool hasMeaningfulContact; bool flag = TryKeepCurrentTarget(enforceRushSearchTimeout: false, out hasMeaningfulContact); if (!flag) { flag = TryAcquireMeaningfulTarget(); hasMeaningfulContact = flag; } if (!flag) { if (HasLostEveryTargetLongEnough()) { WindDownToIdle(); } else { MoveTowardLastKnownTarget(); } } else if (hasMeaningfulContact) { MoveTowardCurrentOrLastTarget(); } else { ((EnemyAI)this).SetDestinationToPosition(_lastKnownTargetPosition, false); } } private void DoRushSnipping() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) bool hasMeaningfulContact; bool flag = TryKeepCurrentTarget(enforceRushSearchTimeout: true, out hasMeaningfulContact); if (!flag) { flag = TryAcquireMeaningfulTarget(); hasMeaningfulContact = flag; } if (!flag) { WindDownToIdle(); return; } if (base.currentSearch != null && base.currentSearch.inProgress) { ((EnemyAI)this).StopSearch(base.currentSearch, true); } if (hasMeaningfulContact) { MoveTowardCurrentOrLastTarget(); return; } base.movingTowardsTargetPlayer = false; ((EnemyAI)this).SetDestinationToPosition(_lastKnownTargetPosition, false); } private bool CanBeginRushSnipping() { if (!TryKeepCurrentTarget(enforceRushSearchTimeout: false, out var _)) { return TryAcquireMeaningfulTarget(); } return true; } private bool TryKeepCurrentTarget(bool enforceRushSearchTimeout, out bool hasMeaningfulContact) { hasMeaningfulContact = false; PlayerControllerB targetPlayer = base.targetPlayer; if (!TargetIsWithinDisengageDistance(targetPlayer)) { DropCurrentTarget(); return false; } if (PlayerHasMeaningfulContact(targetPlayer, DisengageDistance)) { SetTargetWithContact(targetPlayer); hasMeaningfulContact = true; return true; } float num = Time.time - _currentTargetLastContactTime; if (num >= LostContactGracePeriod || (enforceRushSearchTimeout && num >= RushSearchTimeout)) { DropCurrentTarget(); return false; } return true; } private bool TryAcquireMeaningfulTarget() { PlayerControllerB val = FindClosestMeaningfulContactTargetablePlayer(DisengageDistance); if ((Object)(object)val == (Object)null) { return false; } SetTargetWithContact(val); return true; } private void SetTargetWithContact(PlayerControllerB player) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) base.targetPlayer = player; _lastKnownTargetPosition = ((Component)player).transform.position; _currentTargetLastContactTime = Time.time; _lastTargetContactTime = Time.time; } private void DropCurrentTarget() { base.targetPlayer = null; base.movingTowardsTargetPlayer = false; } private bool TargetIsWithinDisengageDistance(PlayerControllerB player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)null && !player.isPlayerDead && ((EnemyAI)this).PlayerIsTargetable(player, false, false, true)) { return Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) <= DisengageDistance; } return false; } private bool HasLostEveryTargetLongEnough() { if ((Object)(object)FindClosestMeaningfulContactTargetablePlayer(DisengageDistance) != (Object)null) { _lastTargetContactTime = Time.time; return false; } return Time.time - _lastTargetContactTime >= LostContactGracePeriod; } private void WindDownToIdle() { _wheelVisualAngle += 180f; ReturnToIdleWalk(); PlayWheelUnwindClientRpc(_wheelVisualAngle); } private void BeginWindup(PlayerControllerB player) { ((EnemyAI)this).StopSearch(base.currentSearch, true); SetTargetWithContact(player); _windupTimer = 0f; _tickingRepeatCount = 0; ConfigureAgentForState(1); SwitchState(1); PlayWindupClientRpc(); } private void BeginRushSnipping() { ((EnemyAI)this).StopSearch(base.currentSearch, true); ConfigureAgentForState(2); SwitchState(2); PlaySnipClientRpc(); } private void ReturnToIdleWalk() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) _windupTimer = 0f; DropCurrentTarget(); _currentTargetLastContactTime = 0f; ConfigureAgentForState(0); SwitchState(0); if (!base.currentSearch.inProgress) { ((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null); } } private void SwitchState(int state) { if (base.currentBehaviourStateIndex != state) { ((EnemyAI)this).SwitchToBehaviourState(state); } } private void ConfigureAgentForState(int state) { ConfigureBodyBlockerForState(state); if (!((Object)(object)base.agent == (Object)null)) { base.agent.speed = state switch { 1 => WindupMoveSpeed, 2 => RushSpeed, _ => WalkSpeed, }; base.agent.angularSpeed = ((state == 2) ? 324f : WalkTurnSpeed); base.agent.acceleration = state switch { 1 => 0.6f, 2 => 36f, _ => 2.6f, }; base.agent.stoppingDistance = state switch { 1 => 2.35f, 2 => 0.6f, _ => 0.85f, }; base.agent.radius = 0.32f; base.agent.obstacleAvoidanceType = (ObstacleAvoidanceType)4; base.agent.avoidancePriority = 35; base.agent.autoBraking = state != 2; } } private void MoveTowardLastKnownTarget() { //IL_0044: 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_003d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.targetPlayer != (Object)null && !base.targetPlayer.isPlayerDead && ((EnemyAI)this).PlayerIsTargetable(base.targetPlayer, false, false, true)) { _lastKnownTargetPosition = ((Component)base.targetPlayer).transform.position; } ((EnemyAI)this).SetDestinationToPosition(_lastKnownTargetPosition, false); } private void MoveTowardCurrentOrLastTarget() { //IL_0051: 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_003d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.targetPlayer != (Object)null && !base.targetPlayer.isPlayerDead && ((EnemyAI)this).PlayerIsTargetable(base.targetPlayer, false, false, true)) { _lastKnownTargetPosition = ((Component)base.targetPlayer).transform.position; ((EnemyAI)this).SetMovingTowardsTargetPlayer(base.targetPlayer); } else { ((EnemyAI)this).SetDestinationToPosition(_lastKnownTargetPosition, false); } } private void RepairAgentIfNeeded() { //IL_0069: 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) if (!((Object)(object)base.agent == (Object)null) && ((Behaviour)base.agent).enabled && !base.agent.isOnNavMesh && !(Time.time < _nextAgentRepairTime)) { _nextAgentRepairTime = Time.time + 0.8f; int num = ((base.agent.areaMask != 0) ? base.agent.areaMask : (-1)); NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(((Component)this).transform.position, ref val, 4f, num) && base.agent.Warp(((NavMeshHit)(ref val)).position)) { ResetNavigationRecovery(); } } } private void TickNavigationRecovery(float deltaTime) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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_01af: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.agent == (Object)null || !((Behaviour)base.agent).enabled || !base.agent.isOnNavMesh) { ResetNavigationRecovery(); return; } Vector3 position = ((Component)this).transform.position; Vector3 val = position - _lastNavigationRecoveryPosition; val.y = 0f; _lastNavigationRecoveryPosition = position; bool num = base.currentBehaviourStateIndex == 1 || base.currentBehaviourStateIndex == 2 || (base.currentSearch != null && base.currentSearch.inProgress); bool flag = base.agent.hasPath && !base.agent.pathPending && base.agent.remainingDistance <= Mathf.Max(base.agent.stoppingDistance + 0.45f, 0.9f); float num2 = Mathf.Max(0.01f, base.agent.speed) * 0.25f; int num3; if (!(((Vector3)(ref val)).sqrMagnitude > 0.0025f)) { Vector3 velocity = base.agent.velocity; num3 = ((((Vector3)(ref velocity)).sqrMagnitude > num2 * num2) ? 1 : 0); } else { num3 = 1; } bool flag2 = (byte)num3 != 0; if (!num || flag || flag2) { _navigationStuckTimer = 0f; return; } _navigationStuckTimer += Mathf.Max(0f, deltaTime); if (_navigationStuckTimer < 1.2f) { return; } _navigationStuckTimer = 0f; _nextAgentRepairTime = Time.time + 0.8f; int num4 = ((base.agent.areaMask != 0) ? base.agent.areaMask : (-1)); NavMeshHit val2 = default(NavMeshHit); if (NavMesh.SamplePosition(((Component)this).transform.position, ref val2, 1.5f, num4)) { base.agent.Warp(((NavMeshHit)(ref val2)).position); } if (base.currentBehaviourStateIndex == 0) { if (base.currentSearch != null && base.currentSearch.inProgress) { ((EnemyAI)this).StopSearch(base.currentSearch, false); } ((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null); } else { Vector3 val3 = (PlayerHasMeaningfulContact(base.targetPlayer, DisengageDistance) ? ((Component)base.targetPlayer).transform.position : _lastKnownTargetPosition); ((EnemyAI)this).SetDestinationToPosition(val3, false); } } private void ResetNavigationRecovery() { //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) _navigationStuckTimer = 0f; _lastNavigationRecoveryPosition = ((Component)this).transform.position; } private PlayerControllerB FindClosestMeaningfulContactTargetablePlayer(float range) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StartOfRound.Instance == (Object)null) { return null; } PlayerControllerB result = null; float num = range; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && ((EnemyAI)this).PlayerIsTargetable(val, false, false, true)) { float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position); if (!(num2 > num) && PlayerHasMeaningfulContact(val, range)) { num = num2; result = val; } } } return result; } private bool PlayerHasMeaningfulContact(PlayerControllerB player, float range) { //IL_0025: 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_008d: 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) if ((Object)(object)player == (Object)null || player.isPlayerDead || !((EnemyAI)this).PlayerIsTargetable(player, false, false, true)) { return false; } float num = Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position); if (num > range) { return false; } if (num <= ProximityAwareness) { return true; } Transform val = (((Object)(object)base.eye != (Object)null) ? base.eye : ((Component)this).transform); Transform val2 = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : ((Component)player).transform); return !IsLineOfSightBlocked(val.position, val2.position); } private PlayerControllerB FindClosestVisibleTargetablePlayer(float range) { //IL_0099: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00ce: 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_00e9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StartOfRound.Instance == (Object)null) { return null; } Transform val = (((Object)(object)base.eye != (Object)null) ? base.eye : ((Component)this).transform); PlayerControllerB result = null; float num = range; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val2 in allPlayerScripts) { if (!((Object)(object)val2 == (Object)null) && !val2.isPlayerDead && ((EnemyAI)this).PlayerIsTargetable(val2, false, false, true)) { Transform val3 = (((Object)(object)val2.gameplayCamera != (Object)null) ? ((Component)val2.gameplayCamera).transform : ((Component)val2).transform); float num2 = Vector3.Distance(val.position, val3.position); if (!(num2 > num) && (!(num2 > ProximityAwareness) || (!(Vector3.Angle(val.forward, val3.position - val.position) > DetectionWidth) && !IsLineOfSightBlocked(val.position, val3.position)))) { num = num2; result = val2; } } } return result; } private bool IsLineOfSightBlocked(Vector3 from, Vector3 to) { //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_000b: 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) if (!RaycastHasNonSelfBlocker(from, to)) { return RaycastHasNonSelfBlocker(to, from); } return true; } private bool RaycastHasNonSelfBlocker(Vector3 from, Vector3 to) { //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_0025: 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_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) Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude <= 0.05f) { return false; } int collidersAndRoomMaskAndDefault = StartOfRound.Instance.collidersAndRoomMaskAndDefault; int num = Physics.RaycastNonAlloc(new Ray(from, val / magnitude), _lineOfSightHits, magnitude, collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { Collider collider = ((RaycastHit)(ref _lineOfSightHits[i])).collider; if (!((Object)(object)collider == (Object)null) && !((Component)collider).transform.IsChildOf(((Component)this).transform)) { return true; } } return false; } private void DamageObjectsInAttackVolume() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_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_007c: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00bb: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (base.currentBehaviourStateIndex != 2 || (Object)(object)attackOrigin == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null) { return; } PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val != (Object)null && PlayerIsInsideScissorsDamageVolume(val)) { TryDamagePlayer(val, requireScissorsVolume: false); } if (!((NetworkBehaviour)this).IsServer) { return; } Vector3 scissorsForward = GetScissorsForward(); Quaternion val2 = Quaternion.LookRotation(scissorsForward, Vector3.up); Vector3 val3 = attackOrigin.position + scissorsForward * 0.825f + Vector3.up * 0.3f; Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(1.35f, 1.05f, 1.925f); int num = Physics.OverlapBoxNonAlloc(val3, val4, _attackOverlapResults, val2, -1, (QueryTriggerInteraction)2); IHittable componentInParent = default(IHittable); for (int i = 0; i < num; i++) { Collider val5 = _attackOverlapResults[i]; _attackOverlapResults[i] = null; if (!((Object)(object)val5 == (Object)null) && !((Component)val5).transform.IsChildOf(((Component)this).transform) && !((Object)(object)((Component)val5).GetComponentInParent() != (Object)null)) { EnemyAICollisionDetect val6 = ((Component)val5).GetComponent() ?? ((Component)val5).GetComponentInParent(); if ((Object)(object)val6 != (Object)null) { TryDamageEnemy(val6, scissorsForward); } else if (((Component)val5).TryGetComponent(ref componentInParent) || (componentInParent = ((Component)val5).GetComponentInParent()) != null) { TryHitGenericHittable(componentInParent, scissorsForward); } } } } public override void OnCollideWithPlayer(Collider other) { ((EnemyAI)this).OnCollideWithPlayer(other); if (base.currentBehaviourStateIndex == 2) { PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false); if ((Object)(object)val != (Object)null) { TryDamagePlayer(val); } } } public override void OnCollideWithEnemy(Collider other, EnemyAI collidedEnemy = null) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) ((EnemyAI)this).OnCollideWithEnemy(other, collidedEnemy); if (((NetworkBehaviour)this).IsServer && base.currentBehaviourStateIndex == 2 && !((Object)(object)collidedEnemy == (Object)null) && !collidedEnemy.isEnemyDead && ColliderIsInsideScissorsDamageVolume(other)) { EnemyAICollisionDetect val = ((Component)other).GetComponent() ?? ((Component)other).GetComponentInParent(); if ((Object)(object)val != (Object)null) { TryDamageEnemy(val, GetScissorsForward()); } } } private void TryDamageEnemy(EnemyAICollisionDetect enemyCollision, Vector3 hitDirection) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)enemyCollision == (Object)null) && !((Object)(object)enemyCollision.mainScript == (Object)null) && !((Object)(object)enemyCollision.mainScript == (Object)(object)this) && !enemyCollision.mainScript.isEnemyDead) { int instanceID = ((Object)enemyCollision.mainScript).GetInstanceID(); if (CanDamageHittable(instanceID) && ((IHittable)enemyCollision).Hit(2, hitDirection, (PlayerControllerB)null, true, 7)) { _lastHittableDamageTimes[instanceID] = Time.realtimeSinceStartup; } } } private void TryHitGenericHittable(IHittable hittable, Vector3 hitDirection) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) Object val = (Object)(object)((hittable is Object) ? hittable : null); if (val == (Object)null) { return; } int instanceID = val.GetInstanceID(); if (!CanDamageHittable(instanceID)) { return; } try { PlayerControllerB val2 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if (hittable.Hit(2, hitDirection, val2, true, 7)) { _lastHittableDamageTimes[instanceID] = Time.realtimeSinceStartup; } } catch (Exception ex) { _lastHittableDamageTimes[instanceID] = Time.realtimeSinceStartup; Plugin.Log.LogWarning((object)("[ScissorsCreatureAI] Failed to hit " + val.name + " with scissors: " + ex.Message)); } } private bool CanDamageHittable(int key) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (_lastHittableDamageTimes.TryGetValue(key, out var value)) { return realtimeSinceStartup - value >= AttackDamageCooldown; } return true; } private void TryDamagePlayer(PlayerControllerB player, bool requireScissorsVolume = true) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00c4: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_0125: 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_00fe: 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_010f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || player.isPlayerDead || !((EnemyAI)this).PlayerIsTargetable(player, false, false, true)) { return; } PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if (((Object)(object)val != (Object)null && (Object)(object)player != (Object)(object)val) || (requireScissorsVolume && !PlayerIsInsideScissorsDamageVolume(player))) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (!_lastDamageTimes.TryGetValue(player.playerClientId, out var value) || !(realtimeSinceStartup - value < AttackDamageCooldown)) { _lastDamageTimes[player.playerClientId] = realtimeSinceStartup; Vector3 val2 = (((Object)(object)attackOrigin != (Object)null) ? attackOrigin.position : ((Component)this).transform.position); Vector3 val3 = ((Component)player).transform.position - val2; Vector3 val4 = ((Vector3)(ref val3)).normalized * 8f; if (player.health <= AttackDamage) { PlaySnipKillAudio(); Vector3 val5 = Vector3.up * 14f; val3 = default(Vector3); player.KillPlayer(val5, true, (CauseOfDeath)17, 7, val3, false); } else { player.DamagePlayer(AttackDamage, true, true, (CauseOfDeath)17, 7, false, val4); } } } private bool PlayerIsInsideScissorsDamageVolume(PlayerControllerB player) { //IL_001f: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_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_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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_008c: 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) if ((Object)(object)player == (Object)null || (Object)(object)attackOrigin == (Object)null) { return false; } Vector3 val = ((Component)player).transform.position + Vector3.up * 0.9f - attackOrigin.position; Vector3 scissorsForward = GetScissorsForward(); Vector3 val2 = Vector3.Cross(Vector3.up, scissorsForward); if (((Vector3)(ref val2)).sqrMagnitude <= 0.001f) { val2 = ((Component)this).transform.right; } ((Vector3)(ref val2)).Normalize(); float num = Vector3.Dot(val, scissorsForward); float num2 = Vector3.Dot(val, val2); float num3 = Vector3.Dot(val, Vector3.up); if (num >= -1.1f && num <= 2.75f && Mathf.Abs(num2) <= 1.35f && num3 >= -0.75f) { return num3 <= 1.35f; } return false; } private bool ColliderIsInsideScissorsDamageVolume(Collider hitCollider) { //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_0013: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hitCollider != (Object)null) { Bounds bounds = hitCollider.bounds; return PointIsInsideScissorsDamageVolume(((Bounds)(ref bounds)).center); } return false; } private bool PointIsInsideScissorsDamageVolume(Vector3 point) { //IL_0010: 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_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_0027: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0056: 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_005e: 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_0048: 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) if ((Object)(object)attackOrigin == (Object)null) { return false; } Vector3 val = point - attackOrigin.position; Vector3 scissorsForward = GetScissorsForward(); Vector3 val2 = Vector3.Cross(Vector3.up, scissorsForward); if (((Vector3)(ref val2)).sqrMagnitude <= 0.001f) { val2 = ((Component)this).transform.right; } ((Vector3)(ref val2)).Normalize(); float num = Vector3.Dot(val, scissorsForward); float num2 = Vector3.Dot(val, val2); float num3 = Vector3.Dot(val, Vector3.up); if (num >= -1.1f && num <= 2.75f && Mathf.Abs(num2) <= 1.35f && num3 >= -0.75f) { return num3 <= 1.35f; } return false; } private Vector3 GetScissorsForward() { //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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) if ((Object)(object)attackOrigin != (Object)null) { Vector3 val = attackOrigin.position - ((Component)this).transform.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.001f) { return ((Vector3)(ref val)).normalized; } } Vector3 val2 = -((Component)this).transform.forward; val2.y = 0f; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.001f)) { return -((Component)this).transform.forward; } return ((Vector3)(ref val2)).normalized; } [ServerRpc(RequireOwnership = false)] public void RequestWheelUnwindServerRpc(ulong playerClientId) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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) //IL_013b: 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_0110: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val2 = default(ServerRpcParams); FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(300173571u, val2, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val, playerClientId); ((NetworkBehaviour)this).__endSendServerRpc(ref val, 300173571u, val2, (RpcDelivery)0); } if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost)) { return; } ((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0; if (!CanUseWindupWheel) { return; } PlayerControllerB val3 = FindPlayerByClientId(playerClientId); if (!((Object)(object)val3 == (Object)null)) { Vector3 val4 = (((Object)(object)_wheelInteractionProxy != (Object)null) ? _wheelInteractionProxy.position : (((Object)(object)wheelBone != (Object)null) ? wheelBone.position : ((Component)this).transform.position)); if (!(Vector3.Distance(((Component)val3).transform.position, val4) > WheelInteractDistance + 1.25f)) { WindDownToIdle(); } } } private PlayerControllerB FindPlayerByClientId(ulong playerClientId) { if ((Object)(object)StartOfRound.Instance == (Object)null) { return null; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; for (int i = 0; i < allPlayerScripts.Length; i++) { if ((Object)(object)allPlayerScripts[i] != (Object)null && allPlayerScripts[i].playerClientId == playerClientId) { return allPlayerScripts[i]; } } return null; } private void ResolveRuntimeReferences() { if ((Object)(object)base.creatureAnimator == (Object)null) { base.creatureAnimator = ((Component)this).GetComponent() ?? ((Component)this).GetComponentInChildren(true); } if ((Object)(object)base.agent == (Object)null) { base.agent = ((Component)this).GetComponent() ?? ((Component)this).GetComponentInChildren(true); } if ((Object)(object)base.creatureSFX == (Object)null) { base.creatureSFX = FindAudioSource("CreatureSFX"); } if ((Object)(object)base.creatureVoice == (Object)null) { base.creatureVoice = FindAudioSource("CreatureVoice"); } if ((Object)(object)tickingAudioSource == (Object)null) { tickingAudioSource = FindAudioSource("TickingAudio"); } if ((Object)(object)alarmAudioSource == (Object)null) { alarmAudioSource = FindAudioSource("AlarmAudio"); } if ((Object)(object)attackOrigin == (Object)null) { attackOrigin = FindChildRecursive(((Component)this).transform, "AttackOrigin") ?? ((Component)this).transform; } if ((Object)(object)wheelBone == (Object)null) { wheelBone = FindChildRecursive(((Component)this).transform, "back_windup_wheel_mount"); } if ((Object)(object)_headTrackBone == (Object)null) { _headTrackBone = FindChildRecursive(((Component)this).transform, "head_track"); } if ((Object)(object)_creatureScanNode == (Object)null) { Transform obj = FindChildRecursive(((Component)this).transform, "ScanNode"); _creatureScanNode = ((obj != null) ? ((Component)obj).GetComponent() : null); } DisableStaleWheelScanNode(); if ((Object)(object)_wheelInteractionProxy == (Object)null) { _wheelInteractionProxy = FindChildRecursive(((Component)this).transform, "BackWindupWheel_InteractionProxy"); } if ((Object)(object)_wheelConnector == (Object)null) { _wheelConnector = FindChildRecursive(((Component)this).transform, "BackWindupWheelConnector"); } if ((Object)(object)bodyBlockerCollider == (Object)null) { object obj2 = ((Component)this).GetComponent(); if (obj2 == null) { obj2 = ((Component)this).GetComponent(); if (obj2 == null) { Transform obj3 = FindChildRecursive(((Component)this).transform, "BodyBlocker"); obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent() : null); } } bodyBlockerCollider = (Collider)obj2; } if ((Object)(object)base.eye == (Object)null) { base.eye = FindChildRecursive(((Component)this).transform, "EyeTransform") ?? ((Component)this).transform; } EnsureWheelConnector(); AlignWheelTargetsAndConnector(); } private void TickScanNodeSubText() { if (!((Object)(object)_creatureScanNode == (Object)null)) { bool canUseWindupWheel = CanUseWindupWheel; if (canUseWindupWheel != _scanNodeShowsWheelHint) { _scanNodeShowsWheelHint = canUseWindupWheel; _creatureScanNode.subText = (canUseWindupWheel ? "Try unwinding the back wheel" : "Try unwinding the back wheel"); } } } private void DisableStaleWheelScanNode() { Transform val = FindChildRecursive(((Component)this).transform, "WheelScanNode"); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); } } private void ConfigureBodyBlockerForState(int state) { if (!((Object)(object)bodyBlockerCollider == (Object)null)) { bodyBlockerCollider.isTrigger = false; bodyBlockerCollider.enabled = true; } } private AudioSource FindAudioSource(string childName) { Transform val = FindChildRecursive(((Component)this).transform, childName); AudioSource val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null); if ((Object)(object)val2 != (Object)null) { return val2; } AudioSource componentInChildren = ((Component)this).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && string.Equals(childName, "TickingAudio", StringComparison.Ordinal)) { Plugin.Log.LogWarning((object)("[ScissorsCreatureAI] Dedicated TickingAudio source is missing; ticking is falling back to shared AudioSource '" + ((Object)componentInChildren).name + "'.")); } return componentInChildren; } private static Transform FindChildRecursive(Transform parent, string name) { if ((Object)(object)parent == (Object)null) { return null; } if (((Object)parent).name == name) { return parent; } for (int i = 0; i < parent.childCount; i++) { Transform val = FindChildRecursive(parent.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private void TickWheelVisual(float deltaTime) { //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_0064: 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_0079: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)wheelBone == (Object)null)) { if (!_capturedWheelBase) { _wheelBaseLocalRotation = wheelBone.localRotation; _capturedWheelBase = true; } float num = ((base.currentBehaviourStateIndex == 2) ? (420f * deltaTime) : 0f); if (num > 0f) { _wheelVisualAngle += num; } wheelBone.localRotation = _wheelBaseLocalRotation * Quaternion.AngleAxis(_wheelVisualAngle, Vector3.up); } } private void AlignWheelTargetsAndConnector() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_002d: 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_005c: 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_0065: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ResolveWheelCenterPosition(); if ((Object)(object)_wheelInteractionProxy != (Object)null) { _wheelInteractionProxy.position = val; _wheelInteractionProxy.rotation = ((Component)this).transform.rotation; } EnsureWheelConnector(); if (!((Object)(object)_wheelConnector == (Object)null)) { Vector3 start = ((Component)this).transform.TransformPoint(WheelConnectorBodyAnchorLocalPosition); AlignConnectorCylinder(_wheelConnector, start, val, 0.055f); } } private Vector3 ResolveWheelCenterPosition() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)wheelBone != (Object)null)) { return ((Component)this).transform.TransformPoint(WheelFallbackLocalPosition); } return wheelBone.position; } private void EnsureWheelConnector() { //IL_00c9: 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) if ((Object)(object)_wheelConnector == (Object)null) { _wheelConnector = FindChildRecursive(((Component)this).transform, "BackWindupWheelConnector"); } if ((Object)(object)_wheelConnector != (Object)null) { return; } GameObject val = GameObject.CreatePrimitive((PrimitiveType)2); ((Object)val).name = "BackWindupWheelConnector"; val.transform.SetParent(((Component)this).transform, false); _wheelConnector = val.transform; Collider component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = val.GetComponent(); if ((Object)(object)component2 == (Object)null) { return; } Material material = component2.material; if (!((Object)(object)material == (Object)null)) { Color val2 = default(Color); ((Color)(ref val2))..ctor(0.035f, 0.03f, 0.028f, 1f); if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", val2); } else if (material.HasProperty("_Color")) { material.color = val2; } } } private void AlignConnectorCylinder(Transform connector, Vector3 start, Vector3 end, float radius) { //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_004c: 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_004e: 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_0063: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_008d: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Vector3 val = end - start; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.04f) { if (((Component)connector).gameObject.activeSelf) { ((Component)connector).gameObject.SetActive(false); } return; } if (!((Component)connector).gameObject.activeSelf) { ((Component)connector).gameObject.SetActive(true); } connector.position = (start + end) * 0.5f; connector.rotation = Quaternion.FromToRotation(Vector3.up, ((Vector3)(ref val)).normalized); Vector3 lossyScale = ((Component)this).transform.lossyScale; connector.localScale = new Vector3(radius / Mathf.Max(0.001f, Mathf.Abs(lossyScale.x)), magnitude * 0.5f / Mathf.Max(0.001f, Mathf.Abs(lossyScale.y)), radius / Mathf.Max(0.001f, Mathf.Abs(lossyScale.z))); } private void TickFootstepAudio(float deltaTime) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.creatureSFX == (Object)null) { return; } if (base.currentBehaviourStateIndex != 0 && base.currentBehaviourStateIndex != 1 && base.currentBehaviourStateIndex != 2) { _footstepAudioTimer = 0f; return; } if (base.currentBehaviourStateIndex == 0 && (Object)(object)base.agent != (Object)null) { Vector3 velocity = base.agent.velocity; if (((Vector3)(ref velocity)).sqrMagnitude < 0.01f) { return; } } bool flag = base.currentBehaviourStateIndex == 2; AudioClip val = ((flag && (Object)(object)attackRunClip != (Object)null) ? attackRunClip : footstepClip); if (!((Object)(object)val == (Object)null)) { _footstepAudioTimer -= deltaTime; if (!(_footstepAudioTimer > 0f)) { float num = (flag ? 0.42f : 1.35f); _footstepAudioTimer = Mathf.Max(0.12f, (val.length > 0f) ? (val.length * 0.9f) : num); base.creatureSFX.PlayOneShot(val, flag ? 1.35f : 1.15f); } } } private void TickWindupTickingAudio() { if (!_windupTickingActive && base.currentBehaviourStateIndex != 1) { StopWindupTicking(resetRepeatCount: true); return; } _windupTickingActive = true; if (!((Object)(object)tickingClip == (Object)null) && !((Object)(object)tickingAudioSource == (Object)null) && !tickingAudioSource.isPlaying) { tickingAudioSource.clip = tickingClip; tickingAudioSource.loop = false; tickingAudioSource.volume = 1.25f; tickingAudioSource.pitch = Mathf.Min(2.5f, 1.15f + (float)_tickingRepeatCount * 0.2f); tickingAudioSource.time = 0f; tickingAudioSource.Play(); _tickingRepeatCount++; } } private void StopWindupTicking(bool resetRepeatCount) { if ((Object)(object)tickingAudioSource != (Object)null) { tickingAudioSource.Stop(); tickingAudioSource.loop = false; tickingAudioSource.pitch = 1f; tickingAudioSource.time = 0f; } if (resetRepeatCount) { _tickingRepeatCount = 0; } } private void TickAttackAlarmAudio() { if (base.currentBehaviourStateIndex != 2) { StopAttackAlarm(); } else if (!((Object)(object)alarmClip == (Object)null) && !((Object)(object)alarmAudioSource == (Object)null) && !alarmAudioSource.isPlaying) { alarmAudioSource.clip = alarmClip; alarmAudioSource.loop = true; alarmAudioSource.volume = 1.25f; alarmAudioSource.pitch = 1f; alarmAudioSource.Play(); } } private void StopAttackAlarm() { if (!((Object)(object)alarmAudioSource == (Object)null)) { alarmAudioSource.Stop(); alarmAudioSource.loop = false; alarmAudioSource.pitch = 1f; alarmAudioSource.time = 0f; } } private void TickSnipAudio(float deltaTime) { if (base.currentBehaviourStateIndex != 2 || snipClips == null || snipClips.Length == 0 || (Object)(object)base.creatureSFX == (Object)null) { return; } _snipAudioTimer -= deltaTime; if (!(_snipAudioTimer > 0f)) { _snipAudioTimer = 0.27f; AudioClip val = snipClips[Random.Range(0, snipClips.Length)]; if ((Object)(object)val != (Object)null) { base.creatureSFX.PlayOneShot(val, 2.6f); } } } private void PlayAttackedByPlayerAudio() { if (!((Object)(object)attackedByPlayerClip == (Object)null)) { AudioSource val = (((Object)(object)base.creatureVoice != (Object)null) ? base.creatureVoice : base.creatureSFX); if ((Object)(object)val != (Object)null) { val.PlayOneShot(attackedByPlayerClip, 9f); } } } private void PlaySnipKillAudio() { if (!((Object)(object)base.creatureSFX == (Object)null) && !((Object)(object)snipKillClip == (Object)null)) { base.creatureSFX.PlayOneShot(snipKillClip, 2.8f); } } private void TickIdleGrowlAudio(float deltaTime) { if (base.currentBehaviourStateIndex == 2) { return; } if (base.currentBehaviourStateIndex != 0 && base.currentBehaviourStateIndex != 1) { _idleGrowlTimer = 0f; } else { if ((Object)(object)idleGrowlClip == (Object)null || (Object)(object)base.creatureVoice == (Object)null) { return; } _idleGrowlTimer -= deltaTime; if (!(_idleGrowlTimer > 0f)) { float num = ((base.currentBehaviourStateIndex == 1) ? 4f : 7f); float num2 = ((base.currentBehaviourStateIndex == 1) ? 7f : 12f); _idleGrowlTimer = Random.Range(num, num2); if (!base.creatureVoice.isPlaying) { base.creatureVoice.PlayOneShot(idleGrowlClip, (base.currentBehaviourStateIndex == 1) ? 1.45f : 1.1f); } } } } [ClientRpc] private void PlayWindupClientRpc() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val2 = default(ClientRpcParams); FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(2316245045u, val2, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendClientRpc(ref val, 2316245045u, val2, (RpcDelivery)0); } if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost)) { ((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0; _windupTickingActive = true; StopAttackAlarm(); StopWindupTicking(resetRepeatCount: true); if ((Object)(object)base.creatureSFX != (Object)null && (Object)(object)windupClip != (Object)null) { base.creatureSFX.PlayOneShot(windupClip, 1.25f); } TickWindupTickingAudio(); } } [ClientRpc] private void PlaySnipClientRpc() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val2 = default(ClientRpcParams); FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(1552068909u, val2, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendClientRpc(ref val, 1552068909u, val2, (RpcDelivery)0); } if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost)) { ((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0; _snipAudioTimer = 0f; _windupTickingActive = false; StopWindupTicking(resetRepeatCount: true); TickAttackAlarmAudio(); } } } [ClientRpc] private void PlayWheelUnwindClientRpc(float wheelAngle) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_00dc: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val2 = default(ClientRpcParams); FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(159684443u, val2, (RpcDelivery)0); ((FastBufferWriter)(ref val)).WriteValueSafe(ref wheelAngle, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendClientRpc(ref val, 159684443u, val2, (RpcDelivery)0); } if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost)) { ((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0; _wheelVisualAngle = wheelAngle; _windupTickingActive = false; StopWindupTicking(resetRepeatCount: true); StopAttackAlarm(); if ((Object)(object)base.creatureSFX != (Object)null && (Object)(object)wheelUnwindClip != (Object)null) { base.creatureSFX.PlayOneShot(wheelUnwindClip); } } } private void OnDisable() { _windupTickingActive = false; StopWindupTicking(resetRepeatCount: true); StopAttackAlarm(); } public override void OnDestroy() { _windupTickingActive = false; StopWindupTicking(resetRepeatCount: true); StopAttackAlarm(); ((EnemyAI)this).OnDestroy(); } public override void HitEnemy(int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1) { ((EnemyAI)this).HitEnemy(force, playerWhoHit, playHitSFX, hitID); if (!base.isEnemyDead) { PlayAttackedByPlayerAudio(); base.enemyHP -= force; if (base.enemyHP <= 0 && ((NetworkBehaviour)this).IsOwner) { ((EnemyAI)this).KillEnemyOnOwnerClient(false); } } } protected override void __initializeVariables() { ((EnemyAI)this).__initializeVariables(); } protected override void __initializeRpcs() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown ((NetworkBehaviour)this).__registerRpc(300173571u, new RpcReceiveHandler(__rpc_handler_300173571), "RequestWheelUnwindServerRpc"); ((NetworkBehaviour)this).__registerRpc(2316245045u, new RpcReceiveHandler(__rpc_handler_2316245045), "PlayWindupClientRpc"); ((NetworkBehaviour)this).__registerRpc(1552068909u, new RpcReceiveHandler(__rpc_handler_1552068909), "PlaySnipClientRpc"); ((NetworkBehaviour)this).__registerRpc(159684443u, new RpcReceiveHandler(__rpc_handler_159684443), "PlayWheelUnwindClientRpc"); ((EnemyAI)this).__initializeRpcs(); } private static void __rpc_handler_300173571(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { ulong playerClientId = default(ulong); ByteUnpacker.ReadValueBitPacked(reader, ref playerClientId); target.__rpc_exec_stage = (__RpcExecStage)1; ((ScissorsCreatureAI)(object)target).RequestWheelUnwindServerRpc(playerClientId); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_2316245045(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0029: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)1; ((ScissorsCreatureAI)(object)target).PlayWindupClientRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_1552068909(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0029: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)1; ((ScissorsCreatureAI)(object)target).PlaySnipClientRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_159684443(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0044: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { float wheelAngle = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref wheelAngle, default(ForPrimitives)); target.__rpc_exec_stage = (__RpcExecStage)1; ((ScissorsCreatureAI)(object)target).PlayWheelUnwindClientRpc(wheelAngle); target.__rpc_exec_stage = (__RpcExecStage)0; } } protected internal override string __getTypeName() { return "ScissorsCreatureAI"; } } [BepInPlugin("y4ngz.lethalcompany.scissorscreature", "Y4NGZ Scissors Creature", "0.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { internal const string BundleFilename = "y4ngzscissorscreature.bundle"; internal const string PrefabName = "Y4NGZScissorsCreature"; internal const string LegacyPrefabName = "LGUScissorsCreature"; internal const string DawnNamespace = "y4ngz_monsters"; internal const string DawnEnemyKey = "snipjack"; internal const string BestiaryText = "Snipjack\n\nDanger level: high\n\nA slow-moving construct with a clockwork wheel on its back and oversized shears mounted forward. It winds itself at whatever it sees ahead of it. If the wheel winds fully, the creature begins rapid snipping until the back wheel is unwound. Unwinding the wheel stops it at once; left alone with nothing in reach, its spring eventually runs down on its own.\n\n"; internal const string ScanNodeSubtitle = "Try unwinding the back wheel"; private const float CreatureScale = 0.7f; private const float ScissorsAgentRadius = 0.32f; internal static ManualLogSource Log; internal static ScissorsCreatureConfig ModConfig; internal static AssetBundle ModAssets; internal static EnemyType EnemyType; private static AudioClip[] _bundleAudioClips; private static bool _netcodeInitialized; private static bool _loggedScanNodeLayer; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; try { InitializeNetcodeRPCs(); ModConfig = new ScissorsCreatureConfig(((BaseUnityPlugin)this).Config); if (!ModConfig.Enabled.Value) { Log.LogInfo((object)"Y4NGZ Scissors Creature is disabled by config."); } else { if (!LoadBundle()) { return; } GameObject val = LoadBundlePrefab(); if ((Object)(object)val == (Object)null) { Log.LogError((object)"[Y4NGZ Scissors Creature] Prefab 'Y4NGZScissorsCreature' not found in y4ngzscissorscreature.bundle."); string[] allAssetNames = ModAssets.GetAllAssetNames(); foreach (string text in allAssetNames) { Log.LogError((object)(" - " + text)); } return; } PreparePrefab(val); EnemyType = CreateEnemyType(val); ScissorsCreatureAI component = val.GetComponent(); if ((Object)(object)component != (Object)null) { ((EnemyAI)component).enemyType = EnemyType; } RegisterWithDawn(val); Log.LogInfo((object)"Y4NGZ Scissors Creature v0.1.2 loaded. Registered as 'Snipjack'."); } } catch (Exception arg) { Log.LogError((object)string.Format("[{0}] Initialization failed: {1}", "Y4NGZ Scissors Creature", arg)); } } private static void RegisterWithDawn(GameObject prefab) { SnipjackSpawnWeights spawnWeights = new SnipjackSpawnWeights(() => ModConfig.SpawnWeightMultiplier.Value); DawnLib.RegisterNetworkPrefab(prefab); DawnLib.DefineEnemy(NamespacedKey.From("y4ngz_monsters", "snipjack"), EnemyType, (Action)delegate(EnemyInfoBuilder builder) { ((BaseInfoBuilder)(object)builder.DefineInside((Action)delegate(EnemyLocationBuilder location) { location.SetWeights((Action>)delegate(WeightTableBuilder table) { table.SetGlobalWeight((IWeighted)(object)spawnWeights); }); }).CreateBestiaryNode("Snipjack\n\nDanger level: high\n\nA slow-moving construct with a clockwork wheel on its back and oversized shears mounted forward. It winds itself at whatever it sees ahead of it. If the wheel winds fully, the creature begins rapid snipping until the back wheel is unwound. Unwinding the wheel stops it at once; left alone with nothing in reach, its spring eventually runs down on its own.\n\n").CreateNameKeyword("snipjack")).AddTags((IEnumerable)(object)new NamespacedKey[5] { Tags.Hostile, Tags.Mechanical, Tags.Killable, Tags.Biped, Tags.Medium }); }); } private static void InitializeNetcodeRPCs() { if (_netcodeInitialized) { return; } _netcodeInitialized = true; Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { MethodInfo[] methods; try { methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch { continue; } foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length == 0) { continue; } try { methodInfo.Invoke(null, null); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[NetcodeInit] " + type.Name + "." + methodInfo.Name + " failed: " + ex.Message)); } } } } } private static bool LoadBundle() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { Log.LogError((object)"[Y4NGZ Scissors Creature] Could not resolve plugin assembly directory."); return false; } string text = Path.Combine(directoryName, "y4ngzscissorscreature.bundle"); if (!File.Exists(text)) { Log.LogError((object)("[Y4NGZ Scissors Creature] Missing asset bundle: " + text)); return false; } ModAssets = AssetBundle.LoadFromFile(text); if ((Object)(object)ModAssets == (Object)null) { Log.LogError((object)("[Y4NGZ Scissors Creature] AssetBundle.LoadFromFile returned null for " + text + ".")); return false; } return true; } private static GameObject LoadBundlePrefab() { GameObject val = ModAssets.LoadAsset("Y4NGZScissorsCreature"); if ((Object)(object)val != (Object)null) { return val; } val = ModAssets.LoadAsset("LGUScissorsCreature"); if ((Object)(object)val != (Object)null) { Log.LogInfo((object)"Loaded legacy prefab 'LGUScissorsCreature' from y4ngzscissorscreature.bundle; runtime registration will still use 'Y4NGZ Scissors Creature'."); return val; } string[] allAssetNames = ModAssets.GetAllAssetNames(); foreach (string text in allAssetNames) { string text2 = text.Replace('\\', '/'); if (!text2.EndsWith("/y4ngzscissorscreature.prefab", StringComparison.OrdinalIgnoreCase) && !text2.EndsWith("/lguscissorscreature.prefab", StringComparison.OrdinalIgnoreCase) && !string.Equals(Path.GetFileNameWithoutExtension(text2), "Y4NGZScissorsCreature", StringComparison.OrdinalIgnoreCase)) { continue; } val = ModAssets.LoadAsset(text); if ((Object)(object)val != (Object)null) { if (text2.EndsWith("/lguscissorscreature.prefab", StringComparison.OrdinalIgnoreCase)) { Log.LogInfo((object)("Loaded legacy prefab asset '" + text2 + "' from y4ngzscissorscreature.bundle.")); } return val; } } return null; } private static void PreparePrefab(GameObject prefab) { //IL_0011: 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_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) AssignUniqueNetworkHash(prefab, "Y4NGZScissorsCreature"); prefab.transform.localScale = Vector3.one * 0.7f; ScissorsCreatureAI scissorsCreatureAI = prefab.GetComponent(); if ((Object)(object)scissorsCreatureAI == (Object)null) { scissorsCreatureAI = prefab.AddComponent(); } ((EnemyAI)scissorsCreatureAI).enemyHP = Mathf.Max(1, ModConfig.Health.Value); Animator val = prefab.GetComponent() ?? prefab.GetComponentInChildren(true); if ((Object)(object)val != (Object)null) { val.applyRootMotion = false; ((EnemyAI)scissorsCreatureAI).creatureAnimator = val; } else { Log.LogWarning((object)"[ScissorsCreature] Prefab has no Animator."); } NavMeshAgent val2 = prefab.GetComponent() ?? prefab.GetComponentInChildren(true); if ((Object)(object)val2 != (Object)null) { ((EnemyAI)scissorsCreatureAI).agent = val2; val2.speed = ModConfig.WalkSpeed.Value; val2.angularSpeed = 11.7f; val2.acceleration = 2.6f; val2.stoppingDistance = 0.85f; val2.radius = 0.32f; val2.height = 1.61f; val2.obstacleAvoidanceType = (ObstacleAvoidanceType)4; val2.avoidancePriority = 35; } else { Log.LogWarning((object)"[ScissorsCreature] Prefab has no NavMeshAgent."); } ((EnemyAI)scissorsCreatureAI).creatureSFX = FindOrCreateAudioSource(prefab, "CreatureSFX"); ((EnemyAI)scissorsCreatureAI).creatureVoice = FindOrCreateAudioSource(prefab, "CreatureVoice"); scissorsCreatureAI.tickingAudioSource = FindOrCreateAudioSource(prefab, "TickingAudio"); scissorsCreatureAI.alarmAudioSource = FindOrCreateAudioSource(prefab, "AlarmAudio"); RecoverAudioClips(scissorsCreatureAI); ((EnemyAI)scissorsCreatureAI).eye = FindOrCreateChild(prefab.transform, "EyeTransform", new Vector3(0f, 1.65f, 0.2f)); ((EnemyAI)scissorsCreatureAI).eye.localPosition = new Vector3(0f, 1.65f, 0.2f); scissorsCreatureAI.attackOrigin = FindOrCreateChild(prefab.transform, "AttackOrigin", new Vector3(0f, 1.05f, 2.2f)); scissorsCreatureAI.attackOrigin.localPosition = new Vector3(0f, 1.05f, 2.2f); scissorsCreatureAI.wheelBone = FindChildRecursive(prefab.transform, "back_windup_wheel_mount"); EnsureBehaviourStates(scissorsCreatureAI); EnsureScanNode(prefab); EnsureCollision(prefab, scissorsCreatureAI); EnsureWheelInteract(prefab); HideWheelArtifacts(prefab); ManualLogSource log = Log; object[] obj = new object[7] { LoadAllAudioClips().Length, null, null, null, null, null, null }; AudioClip[] snipClips = scissorsCreatureAI.snipClips; obj[1] = ((snipClips != null) ? snipClips.Length : 0); obj[2] = (Object)(object)scissorsCreatureAI.footstepClip != (Object)null; obj[3] = (Object)(object)scissorsCreatureAI.attackRunClip != (Object)null; obj[4] = (Object)(object)scissorsCreatureAI.tickingClip != (Object)null; obj[5] = (Object)(object)scissorsCreatureAI.alarmClip != (Object)null; obj[6] = (Object)(object)scissorsCreatureAI.idleGrowlClip != (Object)null; log.LogInfo((object)string.Format("[ScissorsCreature] Audio ready. bundleClips={0}, snips={1}, footstep={2}, run={3}, ticking={4}, alarm={5}, idle={6}.", obj)); } private static void EnsureBehaviourStates(ScissorsCreatureAI ai) { //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) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //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_0063: 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_0076: Expected O, but got Unknown ((EnemyAI)ai).enemyBehaviourStates = (EnemyBehaviourState[])(object)new EnemyBehaviourState[3] { new EnemyBehaviourState { name = "IdleWalk", IsAnimTrigger = true, parameterString = "DoIdleWalk" }, new EnemyBehaviourState { name = "WindupWalk", IsAnimTrigger = true, parameterString = "DoWindupWalk" }, new EnemyBehaviourState { name = "RushSnipping", IsAnimTrigger = true, parameterString = "DoRushSnipping" } }; ((EnemyAI)ai).currentBehaviourStateIndex = 0; ((EnemyAI)ai).previousBehaviourStateIndex = 0; ((EnemyAI)ai).currentBehaviourState = ((EnemyAI)ai).enemyBehaviourStates[0]; } internal static void EnsureScanNode(GameObject prefab) { //IL_0120: 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_0227: Unknown result type (might be due to invalid IL or missing references) ScanNodeProperties val = null; ScanNodeProperties[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (ScanNodeProperties val2 in componentsInChildren) { bool flag = val2.creatureScanID >= 0; bool flag2 = (Object)(object)val != (Object)null && val.creatureScanID >= 0; bool flag3 = string.Equals(((Object)((Component)val2).gameObject).name, "ScanNode", StringComparison.Ordinal); bool flag4 = (Object)(object)val != (Object)null && string.Equals(((Object)((Component)val).gameObject).name, "ScanNode", StringComparison.Ordinal); if ((Object)(object)val == (Object)null || (flag && !flag2) || (flag == flag2 && flag3 && !flag4)) { val = val2; } } if (componentsInChildren.Length > 1) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)$"[Snipjack] Found {componentsInChildren.Length} scan nodes; retiring every duplicate."); } } for (int j = 0; j < componentsInChildren.Length; j++) { if ((Object)(object)componentsInChildren[j] != (Object)(object)val) { RetireExtraScanNode(componentsInChildren[j], val, prefab); } } Transform val3 = (((Object)(object)val != (Object)null) ? ((Component)val).transform : FindOrCreateChild(prefab.transform, "ScanNode", new Vector3(0f, 1.7f, 0f))); ((Object)((Component)val3).gameObject).name = "ScanNode"; TrySetTag(((Component)val3).gameObject, "DoNotSet"); TrySetLayer(((Component)val3).gameObject, "ScanNode"); EnsureHierarchyActive(val3, prefab.transform); ((Component)val3).gameObject.SetActive(true); if (!_loggedScanNodeLayer) { _loggedScanNodeLayer = true; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)($"[Snipjack] Scan node layer resolved to {((Component)val3).gameObject.layer} " + string.Format("(NameToLayer(\"ScanNode\")={0}, fallback 22); ", LayerMask.NameToLayer("ScanNode")) + $"active={((Component)val3).gameObject.activeInHierarchy}.")); } } BoxCollider obj = ((Component)val3).GetComponent() ?? ((Component)val3).gameObject.AddComponent(); ((Collider)obj).enabled = true; ((Collider)obj).isTrigger = true; obj.center = Vector3.zero; obj.size = new Vector3(0.9f, 1.2f, 0.9f); val = val ?? ((Component)val3).gameObject.AddComponent(); val.headerText = "Snipjack"; val.subText = "Try unwinding the back wheel"; val.maxRange = 13; val.minRange = 1; val.requiresLineOfSight = true; val.nodeType = 1; } private static void RetireExtraScanNode(ScanNodeProperties extra, ScanNodeProperties preferred, GameObject root) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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) if ((Object)(object)extra == (Object)null) { return; } Scene scene; if ((Object)(object)((Component)extra).gameObject == (Object)(object)root || ((Object)(object)preferred != (Object)null && (Object)(object)((Component)extra).gameObject == (Object)(object)((Component)preferred).gameObject)) { scene = root.scene; if (((Scene)(ref scene)).IsValid()) { Object.Destroy((Object)(object)extra); } else { Object.DestroyImmediate((Object)(object)extra, true); } return; } GameObject gameObject = ((Component)extra).gameObject; gameObject.SetActive(false); Collider[] components = gameObject.GetComponents(); for (int i = 0; i < components.Length; i++) { components[i].enabled = false; } scene = root.scene; if (((Scene)(ref scene)).IsValid()) { Object.Destroy((Object)(object)gameObject); } else { Object.DestroyImmediate((Object)(object)gameObject, true); } } private static void EnsureCollision(GameObject prefab, ScissorsCreatureAI ai) { //IL_004b: 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_00e7: 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_014f: 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_022e: Unknown result type (might be due to invalid IL or missing references) TrySetTag(prefab, "Enemy"); TrySetLayer(prefab, "Enemies"); CapsuleCollider val = prefab.GetComponent(); if ((Object)(object)val == (Object)null) { val = prefab.AddComponent(); } ((Collider)val).isTrigger = false; val.direction = 1; val.center = new Vector3(0f, 1.12f, 0.05f); val.radius = 0.34f; val.height = 1.85f; ai.bodyBlockerCollider = (Collider)(object)val; Transform val2 = prefab.transform.Find("BodyBlocker"); if ((Object)(object)val2 != (Object)null) { Collider component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null) { component.enabled = false; } ((Component)val2).gameObject.SetActive(false); } Transform val3 = FindOrCreateChild(prefab.transform, "Collision", new Vector3(0f, 1.05f, 2.2f)); val3.localPosition = new Vector3(0f, 1.05f, 2.2f); TrySetTag(((Component)val3).gameObject, "Enemy"); TrySetLayer(((Component)val3).gameObject, "Enemies"); BoxCollider val4 = ((Component)val3).GetComponent(); if ((Object)(object)val4 == (Object)null) { val4 = ((Component)val3).gameObject.AddComponent(); } ((Collider)val4).isTrigger = true; val4.center = Vector3.zero; val4.size = new Vector3(1.7f, 0.95f, 2.3f); Rigidbody val5 = ((Component)val3).GetComponent(); if ((Object)(object)val5 == (Object)null) { val5 = ((Component)val3).gameObject.AddComponent(); } val5.isKinematic = true; val5.useGravity = false; val5.detectCollisions = true; EnemyAICollisionDetect val6 = ((Component)val3).GetComponent(); if ((Object)(object)val6 == (Object)null) { val6 = ((Component)val3).gameObject.AddComponent(); } val6.mainScript = (EnemyAI)(object)ai; val6.alwaysAllowHitting = true; val6.canCollideWithEnemies = true; val6.onlyCollideWhenGrounded = false; DisableLegacySolidCollider(prefab.transform, "PhysicalBodyCollider"); DisableLegacySolidCollider(prefab.transform, "PhysicalHeadCollider"); DisableLegacySolidCollider(prefab.transform, "ScissorsPhysicalCollider"); EnsurePhysicalBox(prefab.transform, ai, "ScissorsDoorwayPhysicalCollider", new Vector3(0f, 1.02f, 0.04f), new Vector3(0.58f, 1.55f, 0.58f)); } private static void EnsurePhysicalBox(Transform root, ScissorsCreatureAI ai, string name, Vector3 localPosition, Vector3 size) { //IL_0002: 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_0024: 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) Transform val = FindOrCreateChild(root, name, localPosition); val.SetParent(root, false); val.localPosition = localPosition; val.localRotation = Quaternion.identity; val.localScale = Vector3.one; TrySetTag(((Component)val).gameObject, "Enemy"); TrySetLayer(((Component)val).gameObject, "Enemies"); BoxCollider val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } ((Collider)val2).enabled = true; ((Collider)val2).isTrigger = false; val2.center = Vector3.zero; val2.size = size; Rigidbody val3 = ((Component)val).GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)val).gameObject.AddComponent(); } val3.isKinematic = true; val3.useGravity = false; val3.detectCollisions = true; EnemyAICollisionDetect val4 = ((Component)val).GetComponent(); if ((Object)(object)val4 == (Object)null) { val4 = ((Component)val).gameObject.AddComponent(); } val4.mainScript = (EnemyAI)(object)ai; val4.alwaysAllowHitting = true; val4.canCollideWithEnemies = true; val4.onlyCollideWhenGrounded = false; } private static void DisableLegacySolidCollider(Transform root, string name) { Transform val = FindChildRecursive(root, name); if (!((Object)(object)val == (Object)null)) { Collider[] components = ((Component)val).GetComponents(); for (int i = 0; i < components.Length; i++) { components[i].enabled = false; } Rigidbody component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.detectCollisions = false; } ((Component)val).gameObject.SetActive(false); } } private static void EnsureWheelInteract(GameObject prefab) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown Transform val = FindChildRecursive(prefab.transform, "BackWindupWheel_InteractionProxy"); if ((Object)(object)val == (Object)null) { val = FindOrCreateChild(prefab.transform, "BackWindupWheel_InteractionProxy", new Vector3(0f, 1.18f, -0.55f)); } val.SetParent(prefab.transform, false); val.localPosition = new Vector3(0f, 1.18f, -0.55f); val.localRotation = Quaternion.identity; val.localScale = Vector3.one; TrySetTag(((Component)val).gameObject, "InteractTrigger"); TrySetLayer(((Component)val).gameObject, "InteractableObject"); BoxCollider val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } ((Collider)val2).isTrigger = true; val2.center = Vector3.zero; val2.size = new Vector3(1.65f, 1.45f, 0.8f); MeshRenderer component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = false; } Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } InteractTrigger val3 = ((Component)val).GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)val).gameObject.AddComponent(); } ((Behaviour)val3).enabled = true; val3.interactable = true; val3.oneHandedItemAllowed = true; val3.twoHandedItemAllowed = true; val3.holdInteraction = true; val3.timeToHold = ModConfig.WheelHoldTime.Value; val3.timeToHoldSpeedMultiplier = 1f; val3.holdTip = "Unwind"; val3.hoverTip = "Unwind wheel : [LMB]"; val3.disabledHoverIcon = null; val3.disabledHoverTip = "[ Wheel slack ]"; val3.interactCooldown = true; val3.cooldownTime = 0.2f; val3.currentCooldownValue = -0.05f; val3.disableTriggerMesh = true; if (val3.onInteract == null) { val3.onInteract = new InteractEvent(); } if (val3.onInteractEarly == null) { val3.onInteractEarly = new InteractEvent(); } if (val3.onInteractEarlyOtherClients == null) { val3.onInteractEarlyOtherClients = new InteractEvent(); } if (val3.onStopInteract == null) { val3.onStopInteract = new InteractEvent(); } if (val3.holdingInteractEvent == null) { val3.holdingInteractEvent = new InteractEventFloat(); } ScissorsWheelInteract scissorsWheelInteract = ((Component)val).GetComponent(); if ((Object)(object)scissorsWheelInteract == (Object)null) { scissorsWheelInteract = ((Component)val).gameObject.AddComponent(); } ((Behaviour)scissorsWheelInteract).enabled = true; } private static void HideWheelArtifacts(GameObject prefab) { Renderer[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { string text = ((Object)val).name ?? string.Empty; string text2 = ((Object)((Component)val).transform).name ?? string.Empty; if (text.IndexOf("BackWindupWheel_MountBracket", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("BackWindupWheel_MountBracket", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("InteractionProxy", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("InteractionProxy", StringComparison.OrdinalIgnoreCase) >= 0) { val.enabled = false; } } } private static EnemyType CreateEnemyType(GameObject prefab) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //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_0100: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown EnemyType val = ScriptableObject.CreateInstance(); val.enemyName = "Snipjack"; val.enemyPrefab = prefab; val.PowerLevel = ModConfig.PowerLevel.Value; val.DiversityPowerLevel = 1; val.MaxCount = Mathf.Max(1, ModConfig.MaxCount.Value); val.canDie = true; val.canBeStunned = true; val.canBeDestroyed = true; val.stunTimeMultiplier = 1f; val.stunGameDifficultyMultiplier = 1f; val.destroyOnDeath = false; val.doorSpeedMultiplier = 1f; val.isOutsideEnemy = false; val.isDaytimeEnemy = false; val.probabilityCurve = new AnimationCurve((Keyframe[])(object)new Keyframe[2] { new Keyframe(0f, 1f), new Keyframe(1f, 1f) }); val.numberSpawnedFalloff = new AnimationCurve((Keyframe[])(object)new Keyframe[2] { new Keyframe(0f, 1f), new Keyframe(1f, 0.65f) }); val.useNumberSpawnedFalloff = true; return val; } private static TerminalNode CreateTerminalNode() { TerminalNode obj = ScriptableObject.CreateInstance(); obj.displayText = "Snipjack\n\nDanger level: high\n\nA slow-moving construct with a clockwork wheel on its back and oversized shears mounted forward. It winds itself at whatever it sees ahead of it. If the wheel winds fully, the creature begins rapid snipping until the back wheel is unwound. Unwinding the wheel stops it at once; left alone with nothing in reach, its spring eventually runs down on its own.\n\n"; obj.creatureName = "Snipjack"; obj.maxCharactersToType = 35; obj.clearPreviousText = true; return obj; } private static TerminalKeyword CreateTerminalKeyword(TerminalNode node) { TerminalKeyword obj = ScriptableObject.CreateInstance(); obj.word = "snipjack"; obj.isVerb = false; obj.specialKeywordResult = node; return obj; } private static AudioSource FindOrCreateAudioSource(GameObject prefab, string childName) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) Transform val = prefab.transform.Find(childName); if ((Object)(object)val == (Object)null) { val = FindOrCreateChild(prefab.transform, childName, Vector3.zero); } AudioSource val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } val2.playOnAwake = false; val2.spatialBlend = 1f; val2.rolloffMode = (AudioRolloffMode)1; val2.minDistance = 3.75f; val2.maxDistance = 30f; return val2; } private static void RecoverAudioClips(ScissorsCreatureAI ai) { if (!((Object)(object)ai == (Object)null)) { AudioClip[] clips = LoadAllAudioClips(); AudioClip val = LoadFirstAudioClip("step_01"); ai.footstepClip = val ?? ai.footstepClip ?? LoadFirstAudioClip("OCULITH_WALK_ONCE_MAIN", "oculith_walk_once_main") ?? FindFirstAudioClip(clips, "walk", "step", "foot") ?? CreateProceduralClip("ScissorsFootstepFallback", 0.2f, 115f, 0.26f); ai.attackRunClip = ai.attackRunClip ?? LoadFirstAudioClip("OCULITH_RUN_ONCE_MAIN", "oculith_run_once_main") ?? FindFirstAudioClip(clips, "run", "rush") ?? ai.footstepClip; ai.tickingClip = ai.tickingClip ?? LoadFirstAudioClip("ticking", "tick") ?? FindFirstAudioClip(clips, "tick", "clock") ?? CreateProceduralClip("ScissorsTickingFallback", 0.12f, 880f, 0.22f); ai.alarmClip = ai.alarmClip ?? LoadFirstAudioClip("alarm", "siren") ?? FindFirstAudioClip(clips, "alarm", "siren") ?? CreateProceduralClip("ScissorsAlarmFallback", 0.7f, 620f, 0.2f); ai.idleGrowlClip = ai.idleGrowlClip ?? LoadFirstAudioClip("03-HUM-NECRO", "hum_necro_idle", "idle_growl") ?? FindFirstAudioClip(clips, "hum", "necro", "idle", "growl") ?? CreateProceduralClip("ScissorsIdleFallback", 0.9f, 58f, 0.18f); ai.snipKillClip = ai.snipKillClip ?? LoadFirstAudioClip("snipkill", "snip_kill") ?? FindFirstAudioClip(clips, "snipkill", "snip kill", "kill", "snip") ?? CreateProceduralClip("ScissorsSnipKillFallback", 0.22f, 1260f, 0.34f); AudioClip val2 = LoadFirstAudioClip("snip"); ai.snipClips = (AudioClip[])((!((Object)(object)val2 != (Object)null)) ? ((Array)(NeedsClipArray(ai.snipClips) ? LoadAudioClipPool("snip01", "snip02", "snip04", "snip05") : ai.snipClips)) : ((Array)new AudioClip[1] { val2 })); if (NeedsClipArray(ai.snipClips)) { AudioClip[] array = SelectAudioClips(clips, 8, "snip", "scissor", "cut", "slash"); ai.snipClips = (AudioClip[])((array.Length != 0) ? ((Array)array) : ((Array)new AudioClip[1] { CreateProceduralClip("ScissorsSnipFallback", 0.14f, 1450f, 0.32f) })); } } } private static AudioClip LoadAudioClip(string clipName, bool warnMissing = true) { if ((Object)(object)ModAssets == (Object)null || string.IsNullOrWhiteSpace(clipName)) { return null; } AudioClip val = ModAssets.LoadAsset(clipName); if ((Object)(object)val == (Object)null) { val = FindExactAudioClip(LoadAllAudioClips(), clipName); } if ((Object)(object)val == (Object)null && warnMissing) { Log.LogWarning((object)("[ScissorsCreature] Missing audio clip in bundle: " + clipName)); } return val; } private static AudioClip LoadFirstAudioClip(params string[] clipNames) { if (clipNames == null) { return null; } for (int i = 0; i < clipNames.Length; i++) { AudioClip val = LoadAudioClip(clipNames[i], warnMissing: false); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static AudioClip[] LoadAudioClipPool(params string[] clipNames) { List list = new List((clipNames != null) ? clipNames.Length : 0); if (clipNames != null) { for (int i = 0; i < clipNames.Length; i++) { AudioClip val = LoadAudioClip(clipNames[i], warnMissing: false); if ((Object)(object)val != (Object)null) { list.Add(val); } } } if (list.Count == 0) { AudioClip val2 = LoadAudioClip("snip", warnMissing: false); if ((Object)(object)val2 != (Object)null) { list.Add(val2); } } return list.ToArray(); } private static bool NeedsClipArray(AudioClip[] clips) { if (clips == null || clips.Length == 0) { return true; } for (int i = 0; i < clips.Length; i++) { if ((Object)(object)clips[i] != (Object)null) { return false; } } return true; } private static AudioClip[] LoadAllAudioClips() { if (_bundleAudioClips != null) { return _bundleAudioClips; } if ((Object)(object)ModAssets == (Object)null) { _bundleAudioClips = Array.Empty(); return _bundleAudioClips; } try { _bundleAudioClips = ModAssets.LoadAllAssets() ?? Array.Empty(); Log.LogInfo((object)("[ScissorsCreature] Bundle audio clips: " + BuildClipNameList(_bundleAudioClips))); } catch (Exception ex) { Log.LogWarning((object)("[ScissorsCreature] Could not enumerate bundle audio clips: " + ex.Message)); _bundleAudioClips = Array.Empty(); } return _bundleAudioClips; } private static AudioClip FindExactAudioClip(AudioClip[] clips, string clipName) { if (clips == null || string.IsNullOrWhiteSpace(clipName)) { return null; } foreach (AudioClip val in clips) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, clipName, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static AudioClip FindFirstAudioClip(AudioClip[] clips, params string[] patterns) { AudioClip[] array = SelectAudioClips(clips, 1, patterns); if (array.Length == 0) { return null; } return array[0]; } private static AudioClip[] SelectAudioClips(AudioClip[] clips, int take, params string[] patterns) { List list = new List(); if (clips == null || patterns == null) { return list.ToArray(); } for (int i = 0; i < clips.Length; i++) { if (list.Count >= take) { break; } AudioClip val = clips[i]; if ((Object)(object)val == (Object)null) { continue; } string text = ((Object)val).name ?? string.Empty; for (int j = 0; j < patterns.Length; j++) { if (!string.IsNullOrWhiteSpace(patterns[j]) && text.IndexOf(patterns[j], StringComparison.OrdinalIgnoreCase) >= 0) { list.Add(val); break; } } } return list.ToArray(); } private static string BuildClipNameList(AudioClip[] clips) { if (clips == null || clips.Length == 0) { return "(none)"; } List list = new List(clips.Length); foreach (AudioClip val in clips) { list.Add(((Object)(object)val != (Object)null) ? $"{((Object)val).name} ({val.length:0.00}s)" : ""); } return string.Join(", ", list); } private static AudioClip CreateProceduralClip(string name, float duration, float frequency, float amplitude) { int num = Mathf.Max(1, Mathf.RoundToInt(duration * 22050f)); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / 22050f; float num3 = Mathf.Clamp01(num2 / 0.02f); float num4 = Mathf.Clamp01((duration - num2) / 0.06f); float num5 = num3 * num4; array[i] = Mathf.Sin(num2 * frequency * MathF.PI * 2f) * amplitude * num5; } AudioClip obj = AudioClip.Create(name, num, 1, 22050, false); obj.SetData(array, 0); Log.LogWarning((object)("[ScissorsCreature] Using generated fallback audio clip '" + name + "'. Rebuild y4ngzscissorscreature.bundle with authored clips for final audio.")); return obj; } private static Transform FindOrCreateChild(Transform parent, string name, Vector3 localPosition) { //IL_0014: 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) Transform val = parent.Find(name); if ((Object)(object)val != (Object)null) { return val; } val = new GameObject(name).transform; val.SetParent(parent, false); val.localPosition = localPosition; return val; } private static Transform FindChildRecursive(Transform parent, string name) { if ((Object)(object)parent == (Object)null) { return null; } if (((Object)parent).name == name) { return parent; } for (int i = 0; i < parent.childCount; i++) { Transform val = FindChildRecursive(parent.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void TrySetTag(GameObject gameObject, string tag) { try { gameObject.tag = tag; } catch (UnityException) { Log.LogWarning((object)("[ScissorsCreature] Tag '" + tag + "' was not found; leaving '" + ((Object)gameObject).name + "' unchanged.")); } } private static void TrySetLayer(GameObject gameObject, string layerName) { if (!((Object)(object)gameObject == (Object)null)) { int num = LayerMask.NameToLayer(layerName); if (num < 0) { num = ResolveLayerFallback(layerName); } if (num >= 0 && num <= 31) { gameObject.layer = num; return; } Log.LogWarning((object)("[ScissorsCreature] Layer '" + layerName + "' was not found; leaving '" + ((Object)gameObject).name + "' unchanged.")); } } private static int ResolveLayerFallback(string layerName) { if (string.Equals(layerName, "ScanNode", StringComparison.OrdinalIgnoreCase)) { return 22; } if (string.Equals(layerName, "Enemies", StringComparison.OrdinalIgnoreCase)) { return 19; } return -1; } private static void EnsureHierarchyActive(Transform child, Transform stopAt) { Transform val = child; while ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(true); if (!((Object)(object)val == (Object)(object)stopAt)) { val = val.parent; continue; } break; } } private static void AssignUniqueNetworkHash(GameObject prefab, string hashKey) { try { NetworkObject val = prefab.GetComponent(); if ((Object)(object)val == (Object)null) { val = prefab.AddComponent(); } uint num = BitConverter.ToUInt32(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("y4ngz.lethalcompany.scissorscreature." + hashKey)), 0); PropertyInfo property = typeof(NetworkObject).GetProperty("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(val, num); return; } FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(val, num); } } catch (Exception arg) { Log.LogError((object)$"[ScissorsCreature] AssignUniqueNetworkHash failed: {arg}"); } } } internal static class PluginInfo { public const string PLUGIN_GUID = "y4ngz.lethalcompany.scissorscreature"; public const string PLUGIN_NAME = "Y4NGZ Scissors Creature"; public const string PLUGIN_VERSION = "0.1.2"; } internal sealed class ScissorsCreatureConfig { public ConfigEntry Enabled { get; } public ConfigEntry SpawnWeightMultiplier { get; } public ConfigEntry MaxCount { get; } public ConfigEntry PowerLevel { get; } public ConfigEntry Health { get; } public ConfigEntry DetectionRange { get; } public ConfigEntry WalkSpeed { get; } public ConfigEntry RushSpeed { get; } public ConfigEntry WindupDuration { get; } public ConfigEntry AttackDamage { get; } public ConfigEntry WheelHoldTime { get; } public ScissorsCreatureConfig(ConfigFile config) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Expected O, but got Unknown bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { ScissorsCreatureConfigMigration.TryMigrate(config, Plugin.Log); ConfigSectionNameMigration.TryMigrate(config, Plugin.Log, "Snipjack"); Enabled = config.Bind("General", "Enabled", true, "Enable the Snipjack encounter."); SpawnWeightMultiplier = config.Bind("Spawning", "SpawnWeightMultiplier", 1f, new ConfigDescription("Multiplier applied to Snipjack's contextual moon/interior spawn policy. 0 disables natural spawns.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 5f), Array.Empty())); MaxCount = config.Bind("Spawning", "MaxCount", 2, new ConfigDescription("Maximum number of living Snipjacks at once.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10), Array.Empty())); PowerLevel = config.Bind("Spawning", "PowerLevel", 2.5f, new ConfigDescription("Indoor enemy power budget cost for each Snipjack.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 20f), Array.Empty())); Health = config.Bind("Core Stats", "Health", 3, new ConfigDescription("Hits the Snipjack can take before dying.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), Array.Empty())); DetectionRange = config.Bind("Detection", "DetectionRange", 28f, new ConfigDescription("Line-of-sight detection range before windup begins.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); WalkSpeed = config.Bind("Movement", "WalkSpeed", 0.286f, new ConfigDescription("Very slow roaming speed.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 5f), Array.Empty())); RushSpeed = config.Bind("Movement", "RushSpeed", 6.24f, new ConfigDescription("Movement speed while rush-snipping.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 15f), Array.Empty())); WindupDuration = config.Bind("Combat", "WindupDuration", 12f, new ConfigDescription("Seconds spent winding up before the attack begins.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 60f), Array.Empty())); AttackDamage = config.Bind("Combat", "AttackDamage", 35, new ConfigDescription("Damage dealt by each rush-snipping hit.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), Array.Empty())); WheelHoldTime = config.Bind("Abilities", "WheelHoldTime", 0.7f, new ConfigDescription("Seconds a player must hold interact to unwind the back wheel.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 5f), Array.Empty())); } finally { config.SaveOnConfigSet = saveOnConfigSet; if (saveOnConfigSet) { config.Save(); } } } } internal static class ScissorsCreatureConfigMigration { private static readonly ConfigDefinition LegacySpawnWeight = new ConfigDefinition("Spawning", "SpawnWeight"); private static readonly Dictionary RemovedDefaults = new Dictionary { { new ConfigDefinition("Movement", "WindupMoveSpeed"), "0.05" }, { new ConfigDefinition("Movement", "WalkTurnSpeed"), "11.7" }, { new ConfigDefinition("Detection", "DetectionWidth"), "75" }, { new ConfigDefinition("Detection", "ProximityAwareness"), "4" }, { new ConfigDefinition("Combat", "AttackDamageCooldown"), "0.45" }, { new ConfigDefinition("Wheel", "WheelInteractDistance"), "3" }, { new ConfigDefinition("Combat", "DisengageDistance"), "20" }, { new ConfigDefinition("Combat", "LostContactGracePeriod"), "7" }, { new ConfigDefinition("Combat", "RushSearchTimeout"), "8" }, { new ConfigDefinition("HeadTracking", "HeadTrackingEnabled"), "true" }, { new ConfigDefinition("HeadTracking", "HeadTrackingRange"), "18" }, { new ConfigDefinition("HeadTracking", "HeadTrackingMaxYaw"), "22" }, { new ConfigDefinition("HeadTracking", "HeadTrackingMaxPitch"), "12" }, { new ConfigDefinition("HeadTracking", "HeadTrackingTurnSpeed"), "90" } }; internal static bool TryMigrate(ConfigFile config, ManualLogSource log) { string configFilePath = config.ConfigFilePath; if (!File.Exists(configFilePath)) { return false; } Dictionary dictionary = null; string text = null; try { dictionary = ReadValues(configFilePath); if (!ContainsLegacyConfig(dictionary)) { return false; } text = GetBackupPath(configFilePath); File.Copy(configFilePath, text, overwrite: false); File.WriteAllText(configFilePath, BuildMigratedConfig(dictionary), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); config.Reload(); } catch (Exception ex) { string text2 = "The original config was not modified."; if (!string.IsNullOrEmpty(text) && File.Exists(text)) { try { File.Copy(text, configFilePath, overwrite: true); config.Reload(); text2 = "The original config was restored from its backup."; } catch (Exception ex2) { text2 = "Automatic restore also failed: " + ex2.GetBaseException().Message + ". Recover manually from " + text + "."; } } if (log != null) { log.LogWarning((object)("[Snipjack] Could not migrate legacy config: " + ex.GetBaseException().Message + " " + text2)); } return false; } List list = FindCustomizedDroppedKeys(dictionary); if (log != null) { log.LogInfo((object)("[Snipjack] Migrated legacy config to the compact DawnLib layout. Backup: " + text)); } if (list.Count > 0 && log != null) { log.LogWarning((object)("[Snipjack] These customized legacy settings are now authored source tuning and were not carried forward: " + string.Join(", ", list))); } return true; } private static bool ContainsLegacyConfig(Dictionary values) { if (values.ContainsKey(LegacySpawnWeight)) { return true; } foreach (ConfigDefinition key in RemovedDefaults.Keys) { if (values.ContainsKey(key)) { return true; } } return false; } private static string BuildMigratedConfig(Dictionary values) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_0091: Expected O, but got Unknown //IL_00bd: 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_00db: Expected O, but got Unknown //IL_00db: Expected O, but got Unknown //IL_00fa: 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_0118: Expected O, but got Unknown //IL_0118: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Expected O, but got Unknown //IL_0278: Expected O, but got Unknown //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Expected O, but got Unknown //IL_030c: Expected O, but got Unknown //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Expected O, but got Unknown //IL_0358: Expected O, but got Unknown string text = GetValue(values, new ConfigDefinition("10 - Spawning", "SpawnWeightMultiplier"), null, null); if (string.IsNullOrWhiteSpace(text)) { text = ((!float.TryParse(GetValue(values, LegacySpawnWeight, null, "18"), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) ? "1" : (result / 18f).ToString("0.###", CultureInfo.InvariantCulture)); } string text2 = GetValue(values, new ConfigDefinition("40 - Movement", "WalkSpeed"), new ConfigDefinition("Movement", "WalkSpeed"), "0.286"); if (IsApproximately(text2, 1.43f) || IsApproximately(text2, 1.1f)) { text2 = "0.286"; } string text3 = GetValue(values, new ConfigDefinition("40 - Movement", "RushSpeed"), new ConfigDefinition("Movement", "RushSpeed"), "6.24"); if (IsApproximately(text3, 4.8f)) { text3 = "6.24"; } string text4 = GetValue(values, new ConfigDefinition("50 - Combat", "WindupDuration"), new ConfigDefinition("Combat", "WindupDuration"), "12"); if (float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && result2 < 11.95f) { text4 = "12"; } StringBuilder stringBuilder = new StringBuilder(); AppendSection(stringBuilder, "00 - General", ("Enabled", GetValue(values, new ConfigDefinition("00 - General", "Enabled"), null, "true"))); AppendSection(stringBuilder, "10 - Spawning", ("SpawnWeightMultiplier", text), ("MaxCount", GetValue(values, new ConfigDefinition("10 - Spawning", "MaxCount"), null, "2")), ("PowerLevel", GetValue(values, new ConfigDefinition("10 - Spawning", "PowerLevel"), null, "2.5"))); AppendSection(stringBuilder, "20 - Core Stats", ("Health", GetValue(values, new ConfigDefinition("20 - Core Stats", "Health"), null, "3"))); AppendSection(stringBuilder, "30 - Detection", ("DetectionRange", GetValue(values, new ConfigDefinition("30 - Detection", "DetectionRange"), new ConfigDefinition("Detection", "DetectionRange"), "28"))); AppendSection(stringBuilder, "40 - Movement", ("WalkSpeed", text2), ("RushSpeed", text3)); AppendSection(stringBuilder, "50 - Combat", ("WindupDuration", text4), ("AttackDamage", GetValue(values, new ConfigDefinition("50 - Combat", "AttackDamage"), new ConfigDefinition("Combat", "AttackDamage"), "35"))); AppendSection(stringBuilder, "60 - Abilities", ("WheelHoldTime", GetValue(values, new ConfigDefinition("60 - Abilities", "WheelHoldTime"), new ConfigDefinition("Wheel", "WheelHoldTime"), "0.7"))); return stringBuilder.ToString(); } private static void AppendSection(StringBuilder output, string section, params (string Key, string Value)[] entries) { output.Append('[').Append(section).AppendLine("]"); for (int i = 0; i < entries.Length; i++) { output.Append(entries[i].Key).Append(" = ").AppendLine(entries[i].Value); } output.AppendLine(); } private static string GetValue(Dictionary values, ConfigDefinition preferred, ConfigDefinition legacy, string fallback) { if (preferred != (ConfigDefinition)null && values.TryGetValue(preferred, out var value)) { return value; } if (legacy != (ConfigDefinition)null && values.TryGetValue(legacy, out value)) { return value; } return fallback; } private static Dictionary ReadValues(string path) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown Dictionary dictionary = new Dictionary(); string text = string.Empty; string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length == 0 || text2.StartsWith("#", StringComparison.Ordinal)) { continue; } if (text2.StartsWith("[", StringComparison.Ordinal) && text2.EndsWith("]", StringComparison.Ordinal)) { text = text2.Substring(1, text2.Length - 2); continue; } int num = text2.IndexOf('='); if (num > 0) { string text3 = text2.Substring(0, num).Trim(); string value = text2.Substring(num + 1).Trim(); dictionary[new ConfigDefinition(text, text3)] = value; } } return dictionary; } private static List FindCustomizedDroppedKeys(Dictionary values) { List list = new List(); foreach (KeyValuePair removedDefault in RemovedDefaults) { if (values.TryGetValue(removedDefault.Key, out var value) && !ValuesEquivalent(value, removedDefault.Value)) { list.Add(removedDefault.Key.Section + "." + removedDefault.Key.Key); } } list.Sort(StringComparer.OrdinalIgnoreCase); return list; } private static bool ValuesEquivalent(string left, string right) { if (string.Equals(left.Trim(), right.Trim(), StringComparison.OrdinalIgnoreCase)) { return true; } if (float.TryParse(left, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(right, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { return Math.Abs(result - result2) < 0.0001f; } return false; } private static bool IsApproximately(string value, float expected) { if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return Math.Abs(result - expected) < 0.01f; } return false; } private static string GetBackupPath(string configPath) { string text = configPath + ".pre-dawn.bak"; if (!File.Exists(text)) { return text; } for (int i = 2; i < 1000; i++) { string text2 = configPath + $".pre-dawn.{i}.bak"; if (!File.Exists(text2)) { return text2; } } throw new IOException("Could not allocate a Snipjack config backup filename."); } } public sealed class ScissorsWheelInteract : MonoBehaviour { private ScissorsCreatureAI _ai; private InteractTrigger _trigger; private bool _configured; private void Start() { Configure(); } private void OnEnable() { Configure(); } private void Update() { if (!_configured) { Configure(); } if (!((Object)(object)_trigger == (Object)null) && !((Object)(object)_ai == (Object)null)) { _trigger.interactable = true; _trigger.hoverTip = "Unwind wheel : [LMB]"; _trigger.disabledHoverIcon = null; _trigger.disabledHoverTip = "[ Wheel slack ]"; _trigger.holdTip = "Unwind"; } } private void Configure() { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown if (_configured) { return; } _ai = ((Component)this).GetComponentInParent(); _trigger = ((Component)this).GetComponent(); if (!((Object)(object)_trigger == (Object)null)) { _trigger.interactable = true; _trigger.oneHandedItemAllowed = true; _trigger.twoHandedItemAllowed = true; _trigger.holdInteraction = true; _trigger.timeToHold = ((Plugin.ModConfig != null) ? Plugin.ModConfig.WheelHoldTime.Value : 0.7f); _trigger.timeToHoldSpeedMultiplier = 1f; _trigger.interactCooldown = true; _trigger.cooldownTime = 0.2f; _trigger.currentCooldownValue = -0.05f; _trigger.hoverTip = "Unwind wheel : [LMB]"; _trigger.disabledHoverIcon = null; _trigger.disabledHoverTip = "[ Wheel slack ]"; _trigger.holdTip = "Unwind"; _trigger.disableTriggerMesh = true; if (_trigger.onInteract == null) { _trigger.onInteract = new InteractEvent(); } if (_trigger.onInteractEarly == null) { _trigger.onInteractEarly = new InteractEvent(); } if (_trigger.onInteractEarlyOtherClients == null) { _trigger.onInteractEarlyOtherClients = new InteractEvent(); } if (_trigger.onStopInteract == null) { _trigger.onStopInteract = new InteractEvent(); } if (_trigger.holdingInteractEvent == null) { _trigger.holdingInteractEvent = new InteractEventFloat(); } ((UnityEvent)(object)_trigger.onInteract).RemoveListener((UnityAction)OnInteract); ((UnityEvent)(object)_trigger.onInteract).AddListener((UnityAction)OnInteract); _configured = (Object)(object)_ai != (Object)null; } } private void OnInteract(PlayerControllerB player) { if (!((Object)(object)_ai == (Object)null) && !((Object)(object)player == (Object)null)) { _ai.RequestWheelUnwindServerRpc(player.playerClientId); } } } internal sealed class SnipjackSpawnWeights : IWeighted, IContextualWeighted { internal const int DefaultWeight = 4; internal const int MaximumWeight = 100; private readonly Func _multiplier; internal SnipjackSpawnWeights(Func multiplier) { _multiplier = multiplier ?? throw new ArgumentNullException("multiplier"); } public int GetWeight() { return Scale(4, 1f); } public int GetWeight(SpawnWeightContext context) { int moonWeight = GetMoonWeight(((SpawnWeightContext)(ref context)).Moon); if (moonWeight <= 0) { return 0; } return Scale(moonWeight, GetDungeonMultiplier(((SpawnWeightContext)(ref context)).Dungeon)); } internal static int GetMoonWeight(DawnMoonInfo moon) { if (moon == null) { return 4; } if (((DawnBaseInfo)(object)moon).HasTag(Tags.Company) || ((DawnBaseInfo)(object)moon).HasTag(Tags.Unimplemented) || KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Test)) { return 0; } if (KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Experimentation)) { return 2; } if (KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Assurance) || KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Vow)) { return 4; } if (KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Offense) || KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.March) || KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Embrion)) { return 6; } if (KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Adamance)) { return 8; } if (KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Rend) || KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Dine)) { return 10; } if (KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Titan) || KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Artifice) || KeyEquals(((DawnBaseInfo)(object)moon).TypedKey, MoonKeys.Liquidation)) { return 12; } if (((DawnBaseInfo)(object)moon).HasTag(Tags.Paid)) { return 9; } ((DawnBaseInfo)(object)moon).HasTag(Tags.Free); return 4; } internal static float GetDungeonMultiplier(DawnDungeonInfo dungeon) { if (dungeon == null) { return 1f; } if (KeyEquals(((DawnBaseInfo)(object)dungeon).TypedKey, DungeonKeys.FacilityFlow) || KeyEquals(((DawnBaseInfo)(object)dungeon).TypedKey, DungeonKeys.FacilityFlowThreeExits) || KeyEquals(((DawnBaseInfo)(object)dungeon).TypedKey, DungeonKeys.FacilityFlowExtraLarge) || ((DawnBaseInfo)(object)dungeon).HasTag(Tags.Industrial) || ((DawnBaseInfo)(object)dungeon).HasTag(Tags.Mechanical) || ((DawnBaseInfo)(object)dungeon).HasTag(Tags.Factory)) { return 1f; } if (KeyEquals(((DawnBaseInfo)(object)dungeon).TypedKey, DungeonKeys.MansionFlow) || ((DawnBaseInfo)(object)dungeon).HasTag(Tags.Gothic) || ((DawnBaseInfo)(object)dungeon).HasTag(Tags.Grand) || ((DawnBaseInfo)(object)dungeon).HasTag(Tags.Ornate)) { return 0.75f; } if (!KeyEquals(((DawnBaseInfo)(object)dungeon).TypedKey, DungeonKeys.MineshaftFlow) && !((DawnBaseInfo)(object)dungeon).HasTag(Tags.Cavern) && !((DawnBaseInfo)(object)dungeon).HasTag(Tags.Quarry)) { ((DawnBaseInfo)(object)dungeon).HasTag(Tags.Flooded); } return 0.5f; } private int Scale(int moonWeight, float dungeonMultiplier) { float num = Mathf.Clamp(_multiplier(), 0f, 5f); return Mathf.Clamp(Mathf.RoundToInt((float)moonWeight * dungeonMultiplier * num), 0, 100); } private static bool KeyEquals(NamespacedKey left, NamespacedKey right) where T : INamespaced { if (left != null && right != null) { return ((object)left).Equals((object?)right); } return false; } } internal static class SnipjackTuning { internal const float WindupMoveSpeed = 0.05f; internal const float WalkTurnSpeed = 11.7f; internal const float DetectionWidth = 75f; internal const float ProximityAwareness = 4f; internal const float AttackDamageCooldown = 0.45f; internal const float WheelInteractDistance = 3f; internal const float DisengageDistance = 20f; internal const float LostContactGracePeriod = 7f; internal const float RushSearchTimeout = 8f; internal const bool HeadTrackingEnabled = true; internal const float HeadTrackingRange = 18f; internal const float HeadTrackingMaxYaw = 22f; internal const float HeadTrackingMaxPitch = 12f; internal const float HeadTrackingTurnSpeed = 90f; } } namespace Y4NGZMonsters.Shared { internal static class ConfigSectionNameMigration { private static readonly IReadOnlyDictionary SectionNames = new Dictionary(StringComparer.Ordinal) { { "00 - General", "General" }, { "10 - Spawning", "Spawning" }, { "20 - Core Stats", "Core Stats" }, { "20 - Video", "Video" }, { "30 - Detection", "Detection" }, { "30 - Encounter Pacing", "Encounter Pacing" }, { "30 - Encounter Rules", "Encounter Rules" }, { "40 - Movement", "Movement" }, { "50 - Combat", "Combat" }, { "60 - Abilities", "Abilities" }, { "60 - Presentation", "Presentation" }, { "60 - Audio", "Audio" }, { "70 - Audio and Presentation", "Audio and Presentation" }, { "99 - Diagnostics", "Diagnostics" } }; private static readonly Regex NumberedSectionHeader = new Regex("^(?[ \\t]*)\\[(?
00 - General|10 - Spawning|20 - Core Stats|20 - Video|30 - Detection|30 - Encounter Pacing|30 - Encounter Rules|40 - Movement|50 - Combat|60 - Abilities|60 - Presentation|60 - Audio|70 - Audio and Presentation|99 - Diagnostics)\\](?[ \\t]*)(?\\r?)$", RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.CultureInvariant); internal static bool TryMigrate(ConfigFile config, ManualLogSource log, string creatureName) { string configFilePath = config.ConfigFilePath; if (!File.Exists(configFilePath)) { return false; } string text = null; try { int replacementCount; string contents = RenameSectionHeaders(File.ReadAllText(configFilePath), out replacementCount); if (replacementCount == 0) { return false; } text = GetBackupPath(configFilePath); File.Copy(configFilePath, text, overwrite: false); File.WriteAllText(configFilePath, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); config.Reload(); if (log != null) { log.LogInfo((object)($"[{creatureName}] Removed numeric prefixes from {replacementCount} config section header(s). " + "The previous config is backed up at '" + text + "'.")); } return true; } catch (Exception ex) { string text2 = "The original config was not modified."; if (!string.IsNullOrEmpty(text) && File.Exists(text)) { try { File.Copy(text, configFilePath, overwrite: true); config.Reload(); text2 = "The original config was restored from its backup."; } catch (Exception ex2) { text2 = "Automatic restore also failed (" + ex2.Message + "). Restore '" + text + "' manually before editing the config."; } } if (log != null) { log.LogWarning((object)("[" + creatureName + "] Could not remove numeric config section prefixes: " + ex.Message + " " + text2)); } return false; } } internal static string RenameSectionHeaders(string text, out int replacementCount) { int count = 0; string result = NumberedSectionHeader.Replace(text, delegate(Match match) { string value = match.Groups["section"].Value; if (!SectionNames.TryGetValue(value, out var value2)) { return match.Value; } count++; return match.Groups["leading"].Value + "[" + value2 + "]" + match.Groups["trailing"].Value + match.Groups["carriage"].Value; }); replacementCount = count; return result; } private static string GetBackupPath(string configPath) { string text = configPath + ".pre-section-names.bak"; int num = 1; while (File.Exists(text)) { text = configPath + $".pre-section-names.{num}.bak"; num++; } return text; } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { } } } namespace Y4NGZScissorsCreature.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }