using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("oance")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Prototype custom enemy for R.E.P.O.")] [assembly: AssemblyFileVersion("0.2.3.0")] [assembly: AssemblyInformationalVersion("0.2.3")] [assembly: AssemblyProduct("EchoStalker")] [assembly: AssemblyTitle("EchoStalker")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EchoStalker { [BepInPlugin("oance.EchoStalker", "EchoStalker", "0.2.3")] [BepInProcess("REPO.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "oance.EchoStalker"; public const string PluginName = "EchoStalker"; public const string PluginVersion = "0.2.3"; public const string RepoLibGuid = "REPOLib"; internal static Plugin Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; internal static PrototypeConfig Settings { get; private set; } internal static bool IsInitialized { get { if ((Object)(object)Instance != (Object)null) { return Settings != null; } return false; } } private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; private void Awake() { Instance = this; Settings = new PrototypeConfig(((BaseUnityPlugin)this).Config); Logger.LogInfo((object)"oance.EchoStalker v0.2.3 loaded; waiting for the Echo Stalker REPOLib bundle."); } } internal sealed class PrototypeConfig { internal ConfigEntry RoamSpeed { get; } internal ConfigEntry ChaseSpeed { get; } internal ConfigEntry CaptureDamage { get; } internal ConfigEntry CaptureDamageInterval { get; } internal PrototypeConfig(ConfigFile config) { RoamSpeed = config.Bind("Movement", "RoamSpeed", 1.7f, "Movement speed while roaming."); ChaseSpeed = config.Bind("Movement", "ChaseBaseSpeed", 8.5f, "Base movement speed while chasing a player. This v0.2 key supersedes the prototype's old ChaseSpeed setting; the monster also gains catch-up speed at range."); CaptureDamage = config.Bind("Capture", "Damage", 20, "Nonlethal damage dealt on capture and on each latched damage tick."); CaptureDamageInterval = config.Bind("Capture", "DamageInterval", 5f, "Seconds between nonlethal damage ticks while latched to a player."); } } } namespace EchoStalker.Runtime { public sealed class EchoStalkerController : MonoBehaviour { private static readonly int AnimatorState = Animator.StringToHash("State"); private static readonly int AnimatorDeath = Animator.StringToHash("Death"); private static readonly FieldInfo? AudioCurrentSnapshotField = typeof(AudioManager).GetField("currentSnapshot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly HashSet AudioIsolationOwners = new HashSet(); private static SoundSnapshot audioSnapshotBeforeIsolation = (SoundSnapshot)1; private static bool audioSnapshotStored; [Header("Required R.E.P.O. components")] [SerializeField] private Enemy enemy; [SerializeField] private EnemyNavMeshAgent agent; [SerializeField] private EnemyHealth health; [SerializeField] private EnemyVision vision; [SerializeField] private EnemyStateSpawn spawnState; [SerializeField] private EnemyStateDespawn despawnState; [SerializeField] private EnemyStateStunned stunnedState; [SerializeField] private Collider bodyCollider; private PhotonView photonView; [Header("Origins")] [SerializeField] private Transform visionOrigin; [SerializeField] private Transform attackOrigin; [SerializeField] private Transform visualRoot; [Header("Presentation")] [SerializeField] private Animator? animator; [SerializeField] private Sound? spawnSound; [SerializeField] private Sound? ambientSound; [SerializeField] private Sound? alertSound; [SerializeField] private Sound? attackSound; [SerializeField] private Sound? captiveSound; [SerializeField] private Sound? hurtSound; [SerializeField] private Sound? deathSound; [Header("Senses")] [SerializeField] [Min(1f)] private float senseRange = 16f; [Header("Roaming")] [SerializeField] [Min(0.1f)] private float roamSpeed = 1.7f; [SerializeField] [Min(0.1f)] private float roamAcceleration = 6f; [SerializeField] [Min(0.1f)] private float roamRepathTime = 2.5f; [Header("Chase")] [SerializeField] [Min(0f)] private float alertTime = 0.85f; [SerializeField] [Min(0.1f)] private float chaseSpeed = 8.5f; [SerializeField] [Min(0.1f)] private float chaseAcceleration = 34f; [Header("Capture")] [SerializeField] [Min(0.1f)] private float captureRange = 2.1f; [SerializeField] [Min(0f)] private float captureWindup = 0.55f; [SerializeField] [Min(0f)] private int captureDamage = 20; [SerializeField] [Min(0.25f)] private float captureDamageInterval = 5f; [SerializeField] [Min(0.25f)] private float sitDistance = 0.7f; [SerializeField] [Min(0.1f)] private float sitFollowSpeed = 5f; [SerializeField] [Min(0.1f)] private float sitFollowAcceleration = 18f; [SerializeField] [Min(0.05f)] private float sitDeadZone = 0.22f; [SerializeField] [Min(0.1f)] private float sitTurnSpeed = 7f; [SerializeField] [Min(0.1f)] private float captureDamageConfirmTimeout = 1.25f; [Header("Thrown object impacts")] [SerializeField] [Min(0.1f)] private float thrownObjectMinSpeed = 2.5f; [SerializeField] [Min(0.1f)] private float thrownObjectMediumSpeed = 5f; [SerializeField] [Min(0.1f)] private float thrownObjectHeavySpeed = 8f; [SerializeField] [Min(0f)] private float thrownObjectDamagePerMass = 5f; [SerializeField] [Min(0f)] private float thrownObjectStunMass = 2f; [SerializeField] [Min(0f)] private float thrownObjectHitCooldown = 0.35f; [Header("Lifecycle")] [SerializeField] [Min(0f)] private float stateDespawnDelay = 0.65f; [SerializeField] [Min(0f)] private float deathDespawnDelay = 2.2f; private PlayerAvatar? target; private EnemyState observedState; private LayerMask visionMask; private float stateTime; private float repathTime; private bool hitApplied; private bool targetClaimed; private bool captureCommitted; private bool captureHealthReady; private bool captureDamageExpected; private bool captureDamageConfirmed; private bool captureDamageObserved; private bool captureHitInFlight; private int lowestObservedTargetHealth; private int healthFloorBeforePendingHit; private int claimedTargetViewId = -1; private int captureHitSequence; private int pendingCaptureHitSequence; private int lastProcessedCaptureHitMasterActorNumber = -1; private int lastProcessedCaptureHitSequence; private int lastProcessedCaptureHitTargetViewId = -1; private int lastProcessedCaptureHitPostHealth; private bool lastProcessedCaptureHitHealDetected; private float captureHitRequestedTime; private float captureAcknowledgedTime; private float nextCaptureDamageTime; private Vector3 sitOffsetDirection; private Quaternion visualRootInitialLocalRotation; private bool localCaptureHealthReady; private bool localCaptureAudioReleased; private int localLowestObservedTargetHealth; private bool holdsAudioIsolation; private bool captiveMixerAssigned; private bool captivePlaybackStartedLogged; private bool captivePlaybackWarningLogged; private float captivePlaybackRequestedTime; private bool dead; private bool deathFinished; private bool despawnCommitted; private float deathTime; private float nextThrownObjectHitTime; private bool setupIsValid; private bool IsHost => SemiFunc.IsMasterClientOrSingleplayer(); private void Awake() { //IL_00fb: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Expected O, but got Unknown //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown if (enemy == null) { enemy = ((Component)this).GetComponent(); } if (agent == null) { agent = ((Component)this).GetComponent(); } if (health == null) { health = ((Component)this).GetComponent(); } if (vision == null) { vision = ((Component)this).GetComponentInChildren(true); } if (spawnState == null) { spawnState = ((Component)this).GetComponentInChildren(true); } if (despawnState == null) { despawnState = ((Component)this).GetComponentInChildren(true); } if (stunnedState == null) { stunnedState = ((Component)this).GetComponentInChildren(true); } if (bodyCollider == null) { bodyCollider = ((Component)this).GetComponent(); } if (photonView == null) { photonView = ((Component)this).GetComponent(); } if (visionOrigin == null) { visionOrigin = ((Component)this).transform; } if (attackOrigin == null) { attackOrigin = ((Component)this).transform; } if (visualRoot == null) { visualRoot = ((Component)this).transform; } visualRootInitialLocalRotation = visualRoot.localRotation; visionMask = SemiFunc.LayerMaskGetVisionObstruct(); ConfigureCaptiveAudioSource(); DisableVanillaStates(); DisableVanillaStates(); DisableVanillaStates(); DisableVanillaStates(); DisableVanillaStates(); if (Plugin.IsInitialized) { roamSpeed = Mathf.Max(0.1f, Plugin.Settings.RoamSpeed.Value); chaseSpeed = Mathf.Max(0.1f, Plugin.Settings.ChaseSpeed.Value); captureDamage = Mathf.Max(0, Plugin.Settings.CaptureDamage.Value); captureDamageInterval = Mathf.Max(0.25f, Plugin.Settings.CaptureDamageInterval.Value); } setupIsValid = ValidateSetup(); if (!setupIsValid) { ((Behaviour)this).enabled = false; return; } health.onDeathStart.AddListener(new UnityAction(OnDeathStart)); health.onDeath.AddListener(new UnityAction(OnDeath)); health.onHurt.AddListener(new UnityAction(OnHurt)); spawnState.OnSpawn.AddListener(new UnityAction(OnSpawn)); } private void OnDestroy() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown ReleaseAudioIsolation(); if ((Object)(object)health != (Object)null) { UnityEvent onDeathStart = health.onDeathStart; if (onDeathStart != null) { onDeathStart.RemoveListener(new UnityAction(OnDeathStart)); } UnityEvent onDeath = health.onDeath; if (onDeath != null) { onDeath.RemoveListener(new UnityAction(OnDeath)); } UnityEvent onHurt = health.onHurt; if (onHurt != null) { onHurt.RemoveListener(new UnityAction(OnHurt)); } } if ((Object)(object)spawnState != (Object)null) { UnityEvent onSpawn = spawnState.OnSpawn; if (onSpawn != null) { onSpawn.RemoveListener(new UnityAction(OnSpawn)); } } Sound? obj = ambientSound; if (obj != null) { obj.Stop(); } Sound? obj2 = captiveSound; if (obj2 != null) { obj2.Stop(); } } private void OnDisable() { ReleaseAudioIsolation(); Sound? obj = captiveSound; if (obj != null) { obj.Stop(); } } private void Update() { //IL_000f: 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_0015: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Invalid comparison between Unknown and I4 //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Invalid comparison between Unknown and I4 //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Invalid comparison between Unknown and I4 //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Invalid comparison between Unknown and I4 //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Invalid comparison between Unknown and I4 //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected I4, but got Unknown if (!setupIsValid) { return; } EnemyState currentState = enemy.CurrentState; if (currentState != observedState) { observedState = currentState; EnterState(currentState); } bool flag = !dead && (int)currentState != 0 && (int)currentState != 11 && (int)currentState != 6; Sound? obj = ambientSound; if (obj != null) { obj.PlayLoop(flag, 0.25f, 0.25f, 1f, 1f); } bool captureStateActive = !dead && (int)currentState == 6; bool flag2 = UpdateLocalCaptureAudio(captureStateActive); Sound? obj2 = captiveSound; if (obj2 != null) { obj2.PlayLoop(flag2, 4f, 8f, 1f, 1f); } ReportCaptivePlayback(captureStateActive, flag2); UpdateReplicatedPresentation(currentState); if (targetClaimed && !dead) { MaintainClaimProtection(); } if (dead) { agent.Stop(0.1f); if (deathFinished) { deathTime += Time.deltaTime; if (IsHost && deathTime >= deathDespawnDelay) { CommitDespawn(); } } } else if ((int)currentState == 11) { agent.Stop(0.1f); stateTime += Time.deltaTime; if (IsHost && stateTime >= stateDespawnDelay) { CommitDespawn(); } } else { if (!IsHost) { return; } if ((int)currentState == 9 && targetClaimed) { stunnedState.Reset(); SetState((EnemyState)(captureCommitted ? 6 : 4)); return; } if (((int)currentState <= 1 || (int)currentState == 9) ? true : false) { agent.Stop(0.1f); return; } stateTime += Time.deltaTime; switch (currentState - 2) { case 0: UpdateRoam(); break; case 1: UpdateAlert(); break; case 2: UpdateChase(); break; case 3: UpdateCaptureWindup(); break; case 4: UpdateCaptured(); break; } } } private void OnCollisionEnter(Collision collision) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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) if (!setupIsValid || !IsHost || dead || targetClaimed || !health.objectHurt || Time.time < nextThrownObjectHitTime) { return; } Rigidbody rigidbody = collision.rigidbody; if ((Object)(object)rigidbody == (Object)null || ((Object)(object)((Component)rigidbody).GetComponent() == (Object)null && (Object)(object)((Component)rigidbody).GetComponentInParent() == (Object)null)) { return; } Vector3 val = collision.relativeVelocity; float magnitude = ((Vector3)(ref val)).magnitude; if (!(magnitude < thrownObjectMinSpeed)) { nextThrownObjectHitTime = Time.time + thrownObjectHitCooldown; float num = ((magnitude >= thrownObjectHeavySpeed) ? 3f : ((magnitude >= thrownObjectMediumSpeed) ? 2f : 1f)); int num2 = Mathf.Max(1, Mathf.RoundToInt(thrownObjectDamagePerMass * num * Mathf.Max(0.5f, rigidbody.mass) * Mathf.Max(0f, health.objectHurtMultiplier))); val = ((Component)this).transform.position - rigidbody.worldCenterOfMass; Vector3 normalized = ((Vector3)(ref val)).normalized; health.Hurt(num2, normalized); UnityEvent onObjectHurt = health.onObjectHurt; if (onObjectHurt != null) { onObjectHurt.Invoke(); } if (!dead && health.objectHurtStun && rigidbody.mass >= thrownObjectStunMass) { stunnedState.Set(2f); } } } private void EnterState(EnemyState state) { //IL_003c: 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_0070: Expected I4, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected I4, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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) stateTime = 0f; repathTime = 0f; hitApplied = false; if ((Object)(object)animator != (Object)null) { animator.SetInteger(AnimatorState, (int)state); } switch (state - 1) { case 0: dead = false; deathFinished = false; despawnCommitted = false; deathTime = 0f; nextThrownObjectHitTime = 0f; target = null; targetClaimed = false; captureCommitted = false; captureHealthReady = false; captureDamageExpected = false; captureDamageConfirmed = false; captureDamageObserved = false; captureHitInFlight = false; lowestObservedTargetHealth = 0; healthFloorBeforePendingHit = 0; claimedTargetViewId = -1; pendingCaptureHitSequence = 0; captureHitRequestedTime = 0f; captureAcknowledgedTime = 0f; nextCaptureDamageTime = 0f; sitOffsetDirection = Vector3.zero; ResetLocalCaptureAudioState(); ReleaseAudioIsolation(); visualRoot.localRotation = visualRootInitialLocalRotation; health.OverrideDamageResistance(0f, 0f); stunnedState.OverrideDisable(0f); bodyCollider.enabled = true; Play(spawnSound); break; case 2: { if (enemy.TargetPlayerViewID > 0) { claimedTargetViewId = enemy.TargetPlayerViewID; } ResetLocalCaptureAudioState(); targetClaimed = true; MaintainClaimProtection(); EnemyNavMeshAgent obj3 = agent; if (obj3 != null) { obj3.Stop(0.1f); } Play(alertSound); break; } case 3: targetClaimed = true; MaintainClaimProtection(); break; case 4: { targetClaimed = true; MaintainClaimProtection(); EnemyNavMeshAgent obj2 = agent; if (obj2 != null) { obj2.Stop(0.1f); } Play(attackSound); break; } case 5: { targetClaimed = true; captureCommitted = true; MaintainClaimProtection(); EnemyNavMeshAgent obj5 = agent; if (obj5 != null) { obj5.Stop(0.1f); } bodyCollider.enabled = false; nextCaptureDamageTime = Time.time + captureDamageInterval; break; } case 8: { EnemyNavMeshAgent obj4 = agent; if (obj4 != null) { obj4.Stop(0.1f); } break; } case 10: { despawnCommitted = false; EnemyNavMeshAgent obj = agent; if (obj != null) { obj.Stop(0.1f); } StopLoops(); ReleaseAudioIsolation(); break; } case 1: case 6: case 7: case 9: break; } } private void UpdateRoam() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Invalid comparison between Unknown and I4 agent.UpdateAgent(roamSpeed, roamAcceleration); repathTime -= Time.deltaTime; if (repathTime <= 0f || !agent.HasPath()) { Vector3 destination = default(Vector3); if (SemiFunc.EnemyRoamPoint(enemy, ref destination)) { agent.SetDestination(destination); } repathTime = roamRepathTime; } PlayerAvatar val = FindTarget(senseRange); if (IsTargetUsable(val)) { target = val; claimedTargetViewId = val.photonView.ViewID; targetClaimed = true; MaintainClaimProtection(); enemy.SetChaseTarget(val); if ((int)enemy.CurrentState != 3) { target = null; claimedTargetViewId = -1; targetClaimed = false; } } } private void UpdateAlert() { agent.Stop(0.1f); if (!IsTargetUsable(target)) { RecoverReplicatedTarget(); } if (!IsTargetUsable(target)) { SetState((EnemyState)11); } else if (stateTime >= alertTime) { SetState((EnemyState)4); } } private void UpdateChase() { //IL_0036: 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_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_0095: 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_00af: Unknown result type (might be due to invalid IL or missing references) if (!IsTargetUsable(target)) { RecoverReplicatedTarget(); } if (!IsTargetUsable(target)) { SetState((EnemyState)11); return; } PlayerAvatar val = target; Vector3 position = val.playerTransform.position; float num = Vector3.Distance(((Component)this).transform.position, position); enemy.SetChaseTimer(); float num2 = chaseSpeed + Mathf.Clamp((num - 4f) * 0.65f, 0f, 4f); agent.UpdateAgent(num2, chaseAcceleration); agent.SetDestination(position); if (num <= captureRange && SemiFunc.PlayerVisionCheckPosition(attackOrigin.position, position, captureRange + 0.5f, val, true)) { SetState((EnemyState)5); } } private void UpdateCaptureWindup() { agent.Stop(0.1f); if (!IsTargetUsable(target)) { RecoverReplicatedTarget(); } if (!IsTargetUsable(target)) { SetState((EnemyState)11); } else if (!hitApplied && stateTime >= captureWindup) { if (!TryCaptureTarget()) { SetState((EnemyState)4); return; } hitApplied = true; SetState((EnemyState)6); } } private void UpdateCaptured() { if (!IsTargetUsable(target)) { RecoverReplicatedTarget(); } if (!IsTargetUsable(target) || (Object)(object)target.playerHealth == (Object)null || target.playerHealth.health <= 0) { SetState((EnemyState)11); return; } MoveBesideTarget(target); PlayerHealth playerHealth = target.playerHealth; if (!captureHealthReady) { if (playerHealth.healthSet) { captureHealthReady = true; lowestObservedTargetHealth = playerHealth.health; captureDamageConfirmed = true; captureDamageObserved = true; captureHitInFlight = false; } return; } int num = playerHealth.health; if (!captureDamageConfirmed) { if (Time.time - captureHitRequestedTime >= captureDamageConfirmTimeout) { SetState((EnemyState)11); } } else if (!captureDamageObserved) { if (num <= lowestObservedTargetHealth) { captureDamageObserved = true; lowestObservedTargetHealth = num; } else if (Time.time - captureAcknowledgedTime >= 0.35f) { SetState((EnemyState)11); } } else if (num > lowestObservedTargetHealth) { SetState((EnemyState)11); } else { lowestObservedTargetHealth = Mathf.Min(lowestObservedTargetHealth, num); if (Time.time >= nextCaptureDamageTime) { BeginCaptureDamageHit(playerHealth); } } } private PlayerAvatar? FindTarget(float range) { //IL_0007: 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) return SemiFunc.PlayerGetNearestPlayerAvatarWithinRange(range, visionOrigin.position, true, visionMask); } private bool TryCaptureTarget() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!IsTargetUsable(target) || (Object)(object)target.playerHealth == (Object)null) { return false; } Vector3 position = target.playerTransform.position; if (Vector3.Distance(attackOrigin.position, position) > captureRange + 0.5f || !SemiFunc.PlayerVisionCheckPosition(attackOrigin.position, position, captureRange + 0.5f, target, true)) { return false; } PlayerHealth playerHealth = target.playerHealth; if (!playerHealth.healthSet) { return false; } captureHealthReady = playerHealth.healthSet; lowestObservedTargetHealth = playerHealth.health; captureCommitted = true; SetSitOffset(target); BeginCaptureDamageHit(playerHealth); return true; } private void BeginCaptureDamageHit(PlayerHealth targetHealth) { if (targetHealth.healthSet) { lowestObservedTargetHealth = Mathf.Min(lowestObservedTargetHealth, targetHealth.health); healthFloorBeforePendingHit = lowestObservedTargetHealth; captureDamageExpected = captureDamage > 0 && targetHealth.health > 1; captureDamageConfirmed = !captureDamageExpected; captureDamageObserved = !captureDamageExpected; captureHitInFlight = captureDamageExpected; captureHitRequestedTime = Time.time; nextCaptureDamageTime = Time.time + captureDamageInterval; if (captureDamageExpected) { pendingCaptureHitSequence = ++captureHitSequence; SendNonlethalCaptureHit(targetHealth, pendingCaptureHitSequence); } } } private void SendNonlethalCaptureHit(PlayerHealth targetHealth, int hitSequence) { int num = SemiFunc.EnemyGetIndex(enemy); if (!GameManager.Multiplayer()) { int num2 = ApplyNonlethalCaptureHit(targetHealth, captureDamage, num); ConfirmCaptureHit(targetHealth.photonView.ViewID, hitSequence, num2); RecordLocalCaptureHealth(num2); return; } photonView.RPC("CaptureHitRPC", (RpcTarget)0, new object[5] { targetHealth.photonView.ViewID, hitSequence, healthFloorBeforePendingHit, captureDamage, num }); } [PunRPC] private void CaptureHitRPC(int targetViewId, int hitSequence, int expectedHealthFloor, int requestedDamage, int enemyIndex, PhotonMessageInfo info) { //IL_0000: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Invalid comparison between Unknown and I4 if (!SemiFunc.MasterOnlyRPC(info)) { return; } PhotonView val = PhotonView.Find(targetViewId); if ((Object)(object)val == (Object)null || !val.IsMine) { return; } PlayerHealth val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInChildren(true) ?? ((Component)val).GetComponentInParent(); if ((Object)(object)val2 == (Object)null) { return; } Player sender = info.Sender; int num = ((sender != null) ? sender.ActorNumber : (-1)); if (num == lastProcessedCaptureHitMasterActorNumber && hitSequence <= lastProcessedCaptureHitSequence) { if (hitSequence == lastProcessedCaptureHitSequence && targetViewId == lastProcessedCaptureHitTargetViewId) { SendCaptureHitResult(targetViewId, hitSequence, lastProcessedCaptureHitPostHealth, lastProcessedCaptureHitHealDetected); } return; } EnemyState currentState = enemy.CurrentState; bool flag = currentState - 3 <= 3; bool flag2 = flag; if (((Behaviour)this).enabled && setupIsValid && !dead && flag2 && (claimedTargetViewId <= 0 || targetViewId == claimedTargetViewId)) { bool flag3 = localCaptureAudioReleased || val2.health > Mathf.Max(1, expectedHealthFloor) || (localCaptureHealthReady && val2.health > localLowestObservedTargetHealth); int num2 = val2.health; if (flag3) { localCaptureAudioReleased = true; ReleaseAudioIsolation(); } else { num2 = ApplyNonlethalCaptureHit(val2, requestedDamage, enemyIndex); RecordLocalCaptureHealth(num2); } lastProcessedCaptureHitMasterActorNumber = num; lastProcessedCaptureHitSequence = hitSequence; lastProcessedCaptureHitTargetViewId = targetViewId; lastProcessedCaptureHitPostHealth = num2; lastProcessedCaptureHitHealDetected = flag3; SendCaptureHitResult(targetViewId, hitSequence, num2, flag3); } } private void SendCaptureHitResult(int targetViewId, int hitSequence, int postHitHealth, bool healDetected) { photonView.RPC("CaptureHitResultRPC", (RpcTarget)2, new object[4] { targetViewId, hitSequence, postHitHealth, healDetected }); } [PunRPC] private void CaptureHitResultRPC(int targetViewId, int hitSequence, int postHitHealth, bool healDetected, PhotonMessageInfo info) { //IL_0033: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient || !captureCommitted || !captureHitInFlight || targetViewId != claimedTargetViewId || hitSequence != pendingCaptureHitSequence || postHitHealth < 1) { return; } EnemyState currentState = enemy.CurrentState; if ((int)currentState != 5 && (int)currentState != 6) { return; } PhotonView val = PhotonView.Find(targetViewId); if (!((Object)(object)val == (Object)null) && SemiFunc.OwnerOnlyRPC(info, val)) { if (healDetected || postHitHealth > healthFloorBeforePendingHit) { captureHitInFlight = false; SetState((EnemyState)11); } else { ConfirmCaptureHit(targetViewId, hitSequence, postHitHealth); } } } private void ConfirmCaptureHit(int targetViewId, int hitSequence, int postHitHealth) { if (hitSequence == pendingCaptureHitSequence && (!GameManager.Multiplayer() || targetViewId == claimedTargetViewId)) { captureHitInFlight = false; captureDamageConfirmed = true; captureDamageObserved = !captureDamageExpected; lowestObservedTargetHealth = Mathf.Min(healthFloorBeforePendingHit, Mathf.Max(1, postHitHealth)); captureAcknowledgedTime = Time.time; } } private static int ApplyNonlethalCaptureHit(PlayerHealth targetHealth, int requestedDamage, int enemyIndex) { int num = Mathf.Min(Mathf.Max(0, requestedDamage), Mathf.Max(0, targetHealth.health - 1)); if (num > 0) { targetHealth.Hurt(num, false, enemyIndex, false); } return targetHealth.health; } private void MoveBesideTarget(PlayerAvatar activeTarget) { //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_0025: 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_0032: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_00a3: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref sitOffsetDirection)).sqrMagnitude < 0.5f) { SetSitOffset(activeTarget); } Vector3 position = activeTarget.playerTransform.position; Vector3 val = position + sitOffsetDirection * sitDistance; NavMeshHit val2 = default(NavMeshHit); val = ((!NavMesh.SamplePosition(val, ref val2, 1.5f, -1)) ? position : ((NavMeshHit)(ref val2)).position); Vector3 val3 = val - ((Component)this).transform.position; val3.y = 0f; if (((Vector3)(ref val3)).magnitude > sitDeadZone) { agent.UpdateAgent(sitFollowSpeed, sitFollowAcceleration); agent.SetDestination(val); } else { agent.Stop(0.1f); } } private void SetSitOffset(PlayerAvatar activeTarget) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_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_005b: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_007e: Unknown result type (might be due to invalid IL or missing references) Vector3 right = activeTarget.playerTransform.right; right.y = 0f; if (((Vector3)(ref right)).sqrMagnitude < 0.01f) { right = Vector3.right; } ((Vector3)(ref right)).Normalize(); Vector3 val = ((Component)this).transform.position - activeTarget.playerTransform.position; val.y = 0f; float num = ((Vector3.Dot(val, right) < 0f) ? (-1f) : 1f); sitOffsetDirection = right * num; } private void RecoverReplicatedTarget() { if (IsClaimedTarget(enemy.TargetPlayerAvatar)) { target = enemy.TargetPlayerAvatar; } } private void MaintainClaimProtection() { health.OverrideDamageResistance(1f, 0.5f); stunnedState.OverrideDisable(0.5f); } private bool UpdateLocalCaptureAudio(bool captureStateActive) { ConfigureCaptiveAudioSource(); if (!captureStateActive) { ReleaseAudioIsolation(); return false; } PlayerAvatar val = (PlayerAvatar)(IsClaimedTarget(target) ? ((object)target) : ((object)enemy.TargetPlayerAvatar)); if (!IsClaimedTarget(val) || !IsLocalPlayer(val)) { ReleaseAudioIsolation(); return false; } PlayerHealth playerHealth = val.playerHealth; if (playerHealth.healthSet) { if (!localCaptureHealthReady) { RecordLocalCaptureHealth(playerHealth.health); } else if (playerHealth.health > localLowestObservedTargetHealth) { localCaptureAudioReleased = true; } else { localLowestObservedTargetHealth = Mathf.Min(localLowestObservedTargetHealth, playerHealth.health); } } if (localCaptureAudioReleased) { ReleaseAudioIsolation(); return false; } AcquireAudioIsolation(); return true; } private void RecordLocalCaptureHealth(int currentHealth) { int num = Mathf.Max(1, currentHealth); if (!localCaptureHealthReady) { localCaptureHealthReady = true; localCaptureAudioReleased = false; localLowestObservedTargetHealth = num; } else { localLowestObservedTargetHealth = Mathf.Min(localLowestObservedTargetHealth, num); } } private void ResetLocalCaptureAudioState() { localCaptureHealthReady = false; localCaptureAudioReleased = false; localLowestObservedTargetHealth = 0; } private void ConfigureCaptiveAudioSource() { AudioSource val = captiveSound?.Source; if ((Object)(object)val == (Object)null) { return; } captiveSound.StartTimeOverride = 0f; val.ignoreListenerPause = true; val.ignoreListenerVolume = false; val.priority = 0; if (!captiveMixerAssigned && !((Object)(object)AudioManager.instance == (Object)null) && !((Object)(object)AudioManager.instance.AudioCutscene == (Object)null)) { AudioSource component = AudioManager.instance.AudioCutscene.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.outputAudioMixerGroup != (Object)null) { val.outputAudioMixerGroup = component.outputAudioMixerGroup; captiveMixerAssigned = true; } } } private void AcquireAudioIsolation() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) AudioManager instance = AudioManager.instance; if (holdsAudioIsolation || (Object)(object)captiveSound?.Source == (Object)null || (Object)(object)instance == (Object)null || !captiveMixerAssigned) { return; } int instanceID = ((Object)this).GetInstanceID(); if (AudioIsolationOwners.Add(instanceID) && AudioIsolationOwners.Count == 1) { if (!TryGetCurrentSoundSnapshot(instance, out audioSnapshotBeforeIsolation)) { audioSnapshotBeforeIsolation = (SoundSnapshot)1; } audioSnapshotStored = true; instance.SetSoundSnapshot((SoundSnapshot)3, 0.05f); } holdsAudioIsolation = true; } private void ReleaseAudioIsolation() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 if (!holdsAudioIsolation) { return; } Sound? obj = captiveSound; if (obj != null) { obj.Stop(); } AudioIsolationOwners.Remove(((Object)this).GetInstanceID()); holdsAudioIsolation = false; if (AudioIsolationOwners.Count == 0 && audioSnapshotStored) { AudioManager instance = AudioManager.instance; if ((Object)(object)instance != (Object)null && (!TryGetCurrentSoundSnapshot(instance, out var snapshot) || (int)snapshot == 3)) { instance.SetSoundSnapshot(audioSnapshotBeforeIsolation, 0.1f); } audioSnapshotStored = false; } } private static bool TryGetCurrentSoundSnapshot(AudioManager audioManager, out SoundSnapshot snapshot) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected I4, but got Unknown if (AudioCurrentSnapshotField?.GetValue(audioManager) is SoundSnapshot val) { snapshot = (SoundSnapshot)(int)val; return true; } snapshot = (SoundSnapshot)1; return false; } private void ReportCaptivePlayback(bool captureStateActive, bool captiveActive) { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Invalid comparison between Unknown and I4 //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_01af: Unknown result type (might be due to invalid IL or missing references) AudioSource val = captiveSound?.Source; if (!captureStateActive) { captivePlaybackStartedLogged = false; captivePlaybackWarningLogged = false; captivePlaybackRequestedTime = 0f; } else { if (!captiveActive || (Object)(object)val == (Object)null) { return; } if (captivePlaybackRequestedTime <= 0f) { captivePlaybackRequestedTime = Time.unscaledTime; } AudioClip clip = val.clip; if (val.isPlaying) { if (!captivePlaybackStartedLogged && Plugin.IsInitialized) { string arg = (((Object)(object)val.outputAudioMixerGroup != (Object)null) ? ((Object)val.outputAudioMixerGroup).name : "direct output"); Plugin.Logger.LogInfo((object)("Captive audio started: clip='" + (((clip != null) ? ((Object)clip).name : null) ?? "") + "', loadState=" + (((clip != null) ? ((object)clip.loadState/*cast due to .constrained prefix*/).ToString() : null) ?? "missing") + ", " + $"volume={val.volume:F2}, mixer='{arg}'.")); } captivePlaybackStartedLogged = true; return; } bool flag = (Object)(object)clip != (Object)null && (int)clip.loadState == 3; if (!captivePlaybackWarningLogged && (flag || Time.unscaledTime - captivePlaybackRequestedTime >= 1.5f) && Plugin.IsInitialized) { Plugin.Logger.LogWarning((object)("Captive audio was requested but is not playing: clip='" + (((clip != null) ? ((Object)clip).name : null) ?? "") + "', loadState=" + (((clip != null) ? ((object)clip.loadState/*cast due to .constrained prefix*/).ToString() : null) ?? "missing") + ", " + $"sourceEnabled={((Behaviour)val).enabled}, active={((Component)val).gameObject.activeInHierarchy}, " + $"mixerAssigned={(Object)(object)val.outputAudioMixerGroup != (Object)null}.")); captivePlaybackWarningLogged = true; } } } private static bool IsLocalPlayer(PlayerAvatar player) { if ((Object)(object)PlayerController.instance != (Object)null && (Object)(object)player == (Object)(object)PlayerController.instance.playerAvatarScript) { return true; } if (!GameManager.Multiplayer()) { return (Object)(object)PlayerController.instance == (Object)null; } if ((Object)(object)player.photonView != (Object)null) { return player.photonView.IsMine; } return false; } private bool IsClaimedTarget(PlayerAvatar? player) { if (IsTargetUsable(player) && (Object)(object)player.photonView != (Object)null) { if (claimedTargetViewId > 0) { return player.photonView.ViewID == claimedTargetViewId; } return true; } return false; } private void UpdateReplicatedPresentation(EnemyState state) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) bodyCollider.enabled = !dead && (int)state != 6 && (int)state != 11; if ((int)state != 6 || (Object)(object)visualRoot == (Object)null) { return; } PlayerAvatar val = (PlayerAvatar)(IsClaimedTarget(target) ? ((object)target) : ((object)enemy.TargetPlayerAvatar)); if (IsClaimedTarget(val)) { Vector3 val2 = val.playerTransform.position - visualRoot.position; val2.y = 0f; if (!(((Vector3)(ref val2)).sqrMagnitude < 0.01f)) { Quaternion val3 = Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up); visualRoot.rotation = Quaternion.Slerp(visualRoot.rotation, val3, 1f - Mathf.Exp((0f - sitTurnSpeed) * Time.deltaTime)); } } } private void SetState(EnemyState next) { //IL_0016: 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_0024: 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) if (IsHost && !dead && enemy.CurrentState != next) { enemy.CurrentState = next; } } private void OnHurt() { if (!targetClaimed) { Play(hurtSound); } } private void OnDeathStart() { dead = true; deathFinished = false; despawnCommitted = false; deathTime = 0f; EnemyNavMeshAgent obj = agent; if (obj != null) { obj.Stop(0.5f); } StopLoops(); Play(deathSound); Animator? obj2 = animator; if (obj2 != null) { obj2.SetTrigger(AnimatorDeath); } } private void OnDeath() { deathFinished = true; deathTime = 0f; } private void OnSpawn() { if (IsHost) { SemiFunc.EnemySpawn(enemy); } } private void Play(Sound? sound) { if (sound != null) { sound.Play(((Component)this).transform, 1f, 1f, 1f, 1f); } } private void StopLoops() { Sound? obj = ambientSound; if (obj != null) { obj.PlayLoop(false, 0.1f, 0.25f, 1f, 1f); } Sound? obj2 = captiveSound; if (obj2 != null) { obj2.PlayLoop(false, 0.1f, 0.25f, 1f, 1f); } ReleaseAudioIsolation(); } private bool ValidateSetup() { string missing = string.Empty; AppendMissing((Object)(object)enemy == (Object)null, "Enemy"); AppendMissing((Object)(object)agent == (Object)null, "EnemyNavMeshAgent"); AppendMissing((Object)(object)health == (Object)null, "EnemyHealth"); AppendMissing((Object)(object)vision == (Object)null, "EnemyVision"); AppendMissing((Object)(object)spawnState == (Object)null, "EnemyStateSpawn"); AppendMissing((Object)(object)despawnState == (Object)null, "EnemyStateDespawn"); AppendMissing((Object)(object)stunnedState == (Object)null, "EnemyStateStunned"); AppendMissing((Object)(object)bodyCollider == (Object)null, "body Collider"); AppendMissing((Object)(object)photonView == (Object)null, "PhotonView"); AppendMissing((Object)(object)visualRoot == (Object)null, "visual root"); AppendMissing((Object)(object)((Component)this).GetComponentInChildren(true) == (Object)null, "EnemyStateChase marker"); AppendMissing((Object)(object)health != (Object)null && health.onDeathStart == null, "EnemyHealth.onDeathStart"); AppendMissing((Object)(object)health != (Object)null && health.onDeath == null, "EnemyHealth.onDeath"); AppendMissing((Object)(object)health != (Object)null && health.onHurt == null, "EnemyHealth.onHurt"); AppendMissing((Object)(object)spawnState != (Object)null && spawnState.OnSpawn == null, "EnemyStateSpawn.OnSpawn"); AppendMissing(ambientSound == null || (Object)(object)ambientSound.Source == (Object)null, "ambient Sound.Source"); AppendMissing(captiveSound == null || (Object)(object)captiveSound.Source == (Object)null, "captive Sound.Source"); if (missing.Length == 0) { return true; } Debug.LogError((object)("[EchoStalker] Prefab setup is incomplete (" + missing + "). Disabling custom AI on '" + ((Object)this).name + "'."), (Object)(object)this); return false; void AppendMissing(bool condition, string item) { if (condition) { missing += ((missing.Length == 0) ? item : (", " + item)); } } } private static bool IsTargetUsable(PlayerAvatar? player) { if ((Object)(object)player != (Object)null && !player.isDisabled && (Object)(object)player.playerTransform != (Object)null && (Object)(object)player.playerHealth != (Object)null) { return player.playerHealth.health > 0; } return false; } private void DisableVanillaStates() where T : Behaviour { T[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (T val in componentsInChildren) { ((Behaviour)val).enabled = false; } } private void CommitDespawn() { if (!despawnCommitted && IsHost) { despawnCommitted = true; despawnState.Despawn(); } } } public sealed class FriendMonsterVisualAnimator : MonoBehaviour { private readonly struct JointPose { internal Transform Transform { get; } internal Quaternion Rotation { get; } internal JointPose(Transform transform) { //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) Transform = transform; Rotation = transform.localRotation; } } private static readonly int MouthOpenProperty = Shader.PropertyToID("_MouthOpen"); [SerializeField] private Enemy enemy; private readonly List fingers = new List(); private Transform? rig; private Transform? torso; private Transform? head; private Transform? leftShoulder; private Transform? rightShoulder; private Transform? leftElbow; private Transform? rightElbow; private Transform? leftWrist; private Transform? rightWrist; private Transform? leftHip; private Transform? rightHip; private Transform? mouth; private Renderer? faceRenderer; private MaterialPropertyBlock? faceProperties; private Vector3 rigPosition; private Vector3 torsoPosition; private Vector3 headPosition; private Vector3 mouthScale; private Quaternion torsoRotation; private Quaternion headRotation; private Quaternion leftShoulderRotation; private Quaternion rightShoulderRotation; private Quaternion leftElbowRotation; private Quaternion rightElbowRotation; private Quaternion leftWristRotation; private Quaternion rightWristRotation; private Quaternion leftHipRotation; private Quaternion rightHipRotation; private float phaseOffset; private float renderedMouthOpen; private bool ready; private void Awake() { //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0207: 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_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0229: 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) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) if (enemy == null) { enemy = ((Component)this).GetComponentInParent(); } rig = FindDescendant("Friend Rig"); torso = FindDescendant("Torso Pivot"); head = FindDescendant("Head Pivot"); leftShoulder = FindDescendant("Left Shoulder Pivot"); rightShoulder = FindDescendant("Right Shoulder Pivot"); leftElbow = FindDescendant("Left Elbow Pivot"); rightElbow = FindDescendant("Right Elbow Pivot"); leftWrist = FindDescendant("Left Wrist Pivot"); rightWrist = FindDescendant("Right Wrist Pivot"); leftHip = FindDescendant("Left Hip Pivot"); rightHip = FindDescendant("Right Hip Pivot"); mouth = FindDescendant("Mouth"); Transform? obj = FindDescendant("Friend Face Decal"); faceRenderer = ((obj != null) ? ((Component)obj).GetComponent() : null); faceProperties = ((!((Object)(object)faceRenderer != (Object)null)) ? ((MaterialPropertyBlock)null) : new MaterialPropertyBlock()); ready = (Object)(object)enemy != (Object)null && (Object)(object)rig != (Object)null && (Object)(object)torso != (Object)null && (Object)(object)head != (Object)null && (Object)(object)leftShoulder != (Object)null && (Object)(object)rightShoulder != (Object)null && (Object)(object)leftElbow != (Object)null && (Object)(object)rightElbow != (Object)null && (Object)(object)leftWrist != (Object)null && (Object)(object)rightWrist != (Object)null && (Object)(object)leftHip != (Object)null && (Object)(object)rightHip != (Object)null && (Object)(object)mouth != (Object)null; if (!ready) { ((Behaviour)this).enabled = false; return; } rigPosition = rig.localPosition; torsoPosition = torso.localPosition; headPosition = head.localPosition; mouthScale = mouth.localScale; torsoRotation = torso.localRotation; headRotation = head.localRotation; leftShoulderRotation = leftShoulder.localRotation; rightShoulderRotation = rightShoulder.localRotation; leftElbowRotation = leftElbow.localRotation; rightElbowRotation = rightElbow.localRotation; leftWristRotation = leftWrist.localRotation; rightWristRotation = rightWrist.localRotation; leftHipRotation = leftHip.localRotation; rightHipRotation = rightHip.localRotation; phaseOffset = (float)(((Object)this).GetInstanceID() & 0xFF) * (1f / 32f); Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name.StartsWith("Finger ", StringComparison.Ordinal) || ((Object)val).name == "Thumb") { fingers.Add(new JointPose(val)); } } } private void Update() { //IL_000f: 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_007b: 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_00a3: Expected I4, but got Unknown //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04d5: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0532: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_05d8: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_05f8: Unknown result type (might be due to invalid IL or missing references) //IL_05ff: Unknown result type (might be due to invalid IL or missing references) //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_0662: Unknown result type (might be due to invalid IL or missing references) //IL_0669: Unknown result type (might be due to invalid IL or missing references) //IL_0674: Unknown result type (might be due to invalid IL or missing references) //IL_0676: Invalid comparison between Unknown and I4 if (ready) { EnemyState currentState = enemy.CurrentState; float num = Time.time + phaseOffset; float num2 = 0f; float num3 = 0f; float num4 = 0f; float num5 = 0f; float num6 = 0f; float num7 = 0f; float num8 = 0f; float num9 = 0f; float num10 = 0f; float num11 = 0f; float num12 = 4f; float num13 = 0f; float num14 = 10f; switch (currentState - 2) { case 0: num2 = num * 2.4f; num3 = Mathf.Abs(Mathf.Sin(num2)) * 0.035f; num8 = 15f; num11 = 5f; num12 = 7f; num13 = 0.08f; num14 = 6f; break; case 1: num2 = num * 5f; num4 = -0.18f; num5 = -16f; num6 = 12f; num7 = -28f; num9 = 12f; num10 = -18f; num11 = 12f; num12 = 2f; num13 = 0.35f; num14 = 13f; break; case 2: num2 = num * 9.5f; num3 = Mathf.Abs(Mathf.Sin(num2)) * 0.09f; num5 = -13f; num6 = 9f; num7 = -8f; num8 = 54f; num9 = 8f; num10 = -24f; num11 = 24f; num12 = 16f + Mathf.Sin(num2 * 1.7f) * 13f; num13 = 0.35f + Mathf.Abs(Mathf.Sin(num2 * 0.55f)) * 0.35f; num14 = 18f; break; case 3: num2 = num * 8f; num4 = -0.12f; num5 = -20f; num6 = 14f; num7 = -72f; num9 = 10f; num10 = -22f; num11 = 18f; num12 = 8f + Mathf.Sin(num2) * 7f; num13 = 0.65f; num14 = 20f; break; case 4: num2 = num * 7.5f; num4 = -0.42f; num3 = Mathf.Sin(num2 * 0.5f) * 0.025f; num5 = -7f + Mathf.Sin(num2 * 0.45f) * 5f; num6 = Mathf.Sin(num2 * 0.65f) * 8f; num7 = -48f; num8 = 20f; num9 = 28f; num10 = -48f; num11 = 38f; num12 = 18f + Mathf.Sin(num2 * 1.6f) * 17f; num13 = SpeechEnvelope(num); num14 = 16f; break; case 7: num4 = -0.28f; num5 = 24f; num6 = -20f; num7 = 25f; num10 = 18f; num12 = 32f; num14 = 9f; break; } float num15 = Mathf.Sin(num2); float num16 = Mathf.Sin(num2 + MathF.PI); float num17 = Mathf.Sin(num2 * 1.9f); float num18 = 1f - Mathf.Exp((0f - num14) * Time.deltaTime); rig.localPosition = Vector3.Lerp(rig.localPosition, rigPosition + Vector3.up * (num4 + num3), num18); torso.localPosition = Vector3.Lerp(torso.localPosition, torsoPosition + Vector3.up * (num3 * 0.25f), num18); head.localPosition = Vector3.Lerp(head.localPosition, headPosition + new Vector3(num17 * 0.012f, num3 * 0.4f, 0f), num18); Rotate(torso, torsoRotation, new Vector3(num5, 0f, num17 * 2.5f), num18); Rotate(head, headRotation, new Vector3(num6, num17 * 4f, (0f - num17) * 2f), num18); Rotate(leftShoulder, leftShoulderRotation, new Vector3(num7 + num15 * num8, 0f, num9), num18); Rotate(rightShoulder, rightShoulderRotation, new Vector3(num7 + num16 * num8, 0f, 0f - num9), num18); Rotate(leftElbow, leftElbowRotation, new Vector3(num10 - num16 * 12f, 0f, 0f), num18); Rotate(rightElbow, rightElbowRotation, new Vector3(num10 - num15 * 12f, 0f, 0f), num18); Rotate(leftWrist, leftWristRotation, new Vector3(num17 * num11, (0f - num15) * num11 * 0.5f, num15 * num11), num18); Rotate(rightWrist, rightWristRotation, new Vector3((0f - num17) * num11, (0f - num16) * num11 * 0.5f, num16 * num11), num18); Rotate(leftHip, leftHipRotation, new Vector3(num16 * num8 * 0.55f, 0f, 0f), num18); Rotate(rightHip, rightHipRotation, new Vector3(num15 * num8 * 0.55f, 0f, 0f), num18); for (int i = 0; i < fingers.Count; i++) { JointPose jointPose = fingers[i]; float num19 = Mathf.Sin(num2 * 1.35f + (float)i * 0.73f) * 8f; jointPose.Transform.localRotation = Quaternion.Slerp(jointPose.Transform.localRotation, jointPose.Rotation * Quaternion.Euler(num12 + num19, 0f, 0f), num18); } mouth.localScale = Vector3.Lerp(mouth.localScale, new Vector3(mouthScale.x, mouthScale.y * (1f + num13 * 2.2f), mouthScale.z), num18); UpdateFaceMouth(((int)currentState == 6) ? num13 : 0f, num18); } } private void OnDisable() { UpdateFaceMouth(0f, 1f); } private static float SpeechEnvelope(float phase) { float num = Mathf.Abs(Mathf.Sin(phase * 10.7f + Mathf.Sin(phase * 2.3f) * 1.4f)); float num2 = 0.38f + Mathf.Abs(Mathf.Sin(phase * 1.37f + 0.4f)) * 0.62f; return Mathf.Clamp01((num - 0.16f) * 1.3f * num2); } private void UpdateFaceMouth(float target, float blend) { if (!((Object)(object)faceRenderer == (Object)null) && faceProperties != null) { renderedMouthOpen = Mathf.Lerp(renderedMouthOpen, target, blend); faceRenderer.GetPropertyBlock(faceProperties); faceProperties.SetFloat(MouthOpenProperty, renderedMouthOpen); faceRenderer.SetPropertyBlock(faceProperties); } } private static void Rotate(Transform? joint, Quaternion rest, Vector3 euler, float blend) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)joint == (Object)null)) { joint.localRotation = Quaternion.Slerp(joint.localRotation, rest * Quaternion.Euler(euler), blend); } } private Transform? FindDescendant(string targetName) { Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == targetName) { return val; } } return null; } } }