using System; using System.Collections; using GameNetcodeStuff; using Unity.Netcode; using UnityEngine; public class DoublewingAI : EnemyAI { public Animator bodyAnimator; private int behaviourStateLastFrame = -1; public AudioSource flappingAudio; public AudioClip[] birdScreechSFX; public AudioClip birdHitGroundSFX; public AISearchRoutine roamGlide; private bool alertingBird; private float glideTime = 10f; private float currentGlideTime; private RaycastHit hit; private bool flyingToOtherBirdLanding; private float avoidingPlayer; public Transform Body; private Vector3 previousPosition; private float flyLayerWeight; [Space(5f)] public float maxSpeed; [Space(5f)] public float speedElevationMultiplier; private float randomYRot; private int velocityAverageCount; private float averageVelocity; private float lerpedElevation; private float timeSinceEnteringFlight; private float randomHeightOffset; private bool birdStunned; private bool oddInterval; private int birdNoisiness = 5; private float timeSinceSquawking; private float velocityInterval; public Rigidbody birdRigidbody; public override void Start() { base.Start(); creatureAnimator.SetInteger("idleType", UnityEngine.Random.Range(0, 2)); creatureAnimator.SetFloat("speedMultiplier", UnityEngine.Random.Range(0.73f, 1.3f)); bodyAnimator.SetFloat("speedMultiplier", UnityEngine.Random.Range(0.8f, 1.2f)); randomHeightOffset = (float)new System.Random(StartOfRound.Instance.randomMapSeed / (int)(base.NetworkObjectId + 1)).NextDouble(); } public override void DaytimeEnemyLeave() { base.DaytimeEnemyLeave(); if (stunNormalizedTimer < 0f && !isEnemyDead) { bodyAnimator.SetBool("flying", value: true); creatureAnimator.SetBool("gliding", value: true); bodyAnimator.SetTrigger("Leave"); } StartCoroutine(flyAwayThenDespawn()); } private IEnumerator flyAwayThenDespawn() { yield return new WaitForSeconds(7f); if (base.IsOwner) { KillEnemyOnOwnerClient(overrideDestroy: true); } } public override void DetectNoise(Vector3 noisePosition, float noiseLoudness, int timesPlayedInOneSpot = 0, int noiseID = 0) { base.DetectNoise(noisePosition, noiseLoudness, timesPlayedInOneSpot, noiseID); if (noiseID == 911 || isEnemyDead || stunNormalizedTimer > 0f) { return; } float num = Vector3.Distance(noisePosition, base.transform.position + Vector3.up * 0.5f); if (Physics.Linecast(base.transform.position, noisePosition, 256)) { noiseLoudness /= 2f; } float num2 = 0.01f; if (!(noiseLoudness / num <= num2)) { Debug.Log($"Heard noise with id {noiseID} at pos: {noisePosition} with loudness: {noiseLoudness}, dist: {num}"); if (currentBehaviourStateIndex == 0 && !alertingBird) { alertingBird = true; AlertBirdServerRpc(); } } } public void StunBird() { if (birdStunned) { return; } birdStunned = true; agent.speed = 0f; DoublewingAI[] array = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); for (int i = 0; i < array.Length; i++) { if (!(array[i] == this) && Vector3.Distance(array[i].transform.position, base.transform.position) < 8f) { array[i].AlertBirdByOther(); } } flappingAudio.Stop(); creatureAnimator.SetBool("stunned", value: true); bodyAnimator.SetBool("stunned", value: true); } public void UnstunBird() { if (birdStunned) { birdStunned = false; creatureAnimator.SetBool("stunned", value: false); bodyAnimator.SetBool("stunned", value: false); if (currentBehaviourStateIndex == 0) { SwitchToBehaviourStateOnLocalClient(1); } } } public override void DoAIInterval() { base.DoAIInterval(); if (daytimeEnemyLeaving || isEnemyDead || StartOfRound.Instance.allPlayersDead || stunNormalizedTimer > 0f) { return; } switch (currentBehaviourStateIndex) { case 0: oddInterval = !oddInterval; if (oddInterval && !alertingBird && (bool)CheckLineOfSightForPlayer(80f, 8, 4)) { alertingBird = true; AlertBirdServerRpc(); } break; case 1: { behaviourStateLastFrame = 1; creatureAnimator.SetBool("gliding", value: true); bodyAnimator.SetBool("flying", value: true); agent.speed = Mathf.Clamp(agent.speed + AIIntervalTime * 4f, 5f, 19f); if (!flyingToOtherBirdLanding && avoidingPlayer <= 0f && !roamGlide.inProgress) { StartSearch(base.transform.position, roamGlide); } if (avoidingPlayer > 0f) { avoidingPlayer -= AIIntervalTime; if (Vector3.Distance(base.transform.position, destination) < 3f) { avoidingPlayer = 0f; } break; } PlayerControllerB playerControllerB = CheckLineOfSightForPlayer(80f, 10, 8); if (oddInterval && (bool)playerControllerB) { Transform transform = ChooseFarthestNodeFromPosition(playerControllerB.transform.position, avoidLineOfSight: false, UnityEngine.Random.Range(0, allAINodes.Length / 2)); if (SetDestinationToPosition(transform.position)) { avoidingPlayer = UnityEngine.Random.Range(10, 20); StopSearch(roamGlide); } } currentGlideTime += AIIntervalTime; if (!(currentGlideTime > glideTime)) { break; } currentGlideTime = 0f; if (flyingToOtherBirdLanding) { if (!SetDestinationToPosition(destination, checkForPath: true)) { flyingToOtherBirdLanding = false; glideTime = 5f; break; } if (Vector3.Distance(base.transform.position, destination) < 3f) { if (!TryLanding()) { flyingToOtherBirdLanding = false; glideTime = 5f; } else { SwitchToBehaviourState(0); } break; } } for (int i = 0; i < RoundManager.Instance.SpawnedEnemies.Count; i++) { if (RoundManager.Instance.SpawnedEnemies[i].enemyType == enemyType && RoundManager.Instance.SpawnedEnemies[i].currentBehaviourStateIndex == 0 && Vector3.Distance(base.transform.position, RoundManager.Instance.SpawnedEnemies[i].transform.position) < 100f) { Vector3 randomNavMeshPositionInRadius = RoundManager.Instance.GetRandomNavMeshPositionInRadius(RoundManager.Instance.SpawnedEnemies[i].transform.position); if (SetDestinationToPosition(randomNavMeshPositionInRadius, checkForPath: true)) { StopSearch(roamGlide); flyingToOtherBirdLanding = true; glideTime = 2f; } break; } } if (!flyingToOtherBirdLanding) { if (TryLanding()) { SwitchToBehaviourState(0); } else { glideTime = 10f; } } break; } } } public bool TryLanding() { if (Physics.Raycast(new Vector3(base.transform.position.x, eye.position.y, base.transform.position.z), Vector3.down, out hit, 60f, StartOfRound.Instance.collidersAndRoomMaskAndDefault)) { if (Physics.CheckSphere(hit.point, 16f, StartOfRound.Instance.playersMask, QueryTriggerInteraction.Ignore)) { return false; } if (Vector3.Distance(hit.point, base.transform.position) > 1f) { if (SetDestinationToPosition(hit.point, checkForPath: true)) { agent.Warp(destination); return true; } return false; } return true; } return false; } [ServerRpc(RequireOwnership = false)] public void AlertBirdServerRpc() { NetworkManager networkManager = base.NetworkManager; if ((object)networkManager != null && networkManager.IsListening) { if (__rpc_exec_stage != __RpcExecStage.Server && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams serverRpcParams = default(ServerRpcParams); FastBufferWriter bufferWriter = __beginSendServerRpc(838150599u, serverRpcParams, RpcDelivery.Reliable); __endSendServerRpc(ref bufferWriter, 838150599u, serverRpcParams, RpcDelivery.Reliable); } if (__rpc_exec_stage == __RpcExecStage.Server && (networkManager.IsServer || networkManager.IsHost)) { AlertBirdClientRpc(); } } } [ClientRpc] public void AlertBirdClientRpc() { NetworkManager networkManager = base.NetworkManager; if ((object)networkManager != null && networkManager.IsListening) { if (__rpc_exec_stage != __RpcExecStage.Client && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams clientRpcParams = default(ClientRpcParams); FastBufferWriter bufferWriter = __beginSendClientRpc(3264241129u, clientRpcParams, RpcDelivery.Reliable); __endSendClientRpc(ref bufferWriter, 3264241129u, clientRpcParams, RpcDelivery.Reliable); } if (__rpc_exec_stage == __RpcExecStage.Client && (networkManager.IsClient || networkManager.IsHost)) { AlertBird(); } } } public void AlertBird() { DoublewingAI[] array = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); for (int i = 0; i < array.Length; i++) { if (!(array[i] == this) && Vector3.Distance(array[i].transform.position, base.transform.position) < 8f) { array[i].AlertBirdByOther(); } } SwitchToBehaviourStateOnLocalClient(1); alertingBird = false; } public void AlertBirdByOther() { if (!daytimeEnemyLeaving) { SwitchToBehaviourStateOnLocalClient(1); } } public override void Update() { base.Update(); if (isEnemyDead || StartOfRound.Instance.allPlayersDead) { return; } SetFlyDirection(); if (daytimeEnemyLeaving) { return; } timeSinceSquawking += Time.deltaTime; if (stunNormalizedTimer > 0f) { StunBird(); } else { UnstunBird(); } switch (currentBehaviourStateIndex) { case 0: if (behaviourStateLastFrame != 0) { behaviourStateLastFrame = 0; randomYRot = UnityEngine.Random.Range(0f, 360f); agent.speed = 0f; creatureAnimator.SetBool("gliding", value: false); bodyAnimator.SetBool("flying", value: false); flyingToOtherBirdLanding = false; timeSinceEnteringFlight = 0f; } flyLayerWeight = Mathf.Max(0f, flyLayerWeight - Time.deltaTime * 0.28f); timeSinceEnteringFlight += Time.deltaTime; break; case 1: if (behaviourStateLastFrame != 1) { behaviourStateLastFrame = 1; timeSinceEnteringFlight = 0f; creatureAnimator.SetBool("gliding", value: true); bodyAnimator.SetBool("flying", value: true); int num = RoundManager.PlayRandomClip(creatureSFX, enemyType.audioClips); WalkieTalkie.TransmitOneShotAudio(creatureSFX, enemyType.audioClips[num], 0.7f); RoundManager.Instance.PlayAudibleNoise(base.transform.position, 12f, 0.6f, 0, noiseIsInsideClosedShip: false, 911); glideTime = UnityEngine.Random.Range(8f, 20f); } timeSinceEnteringFlight += Time.deltaTime; flyLayerWeight = Mathf.Min(1f, flyLayerWeight + Time.deltaTime * 0.33f); break; } } private void BirdScreech() { RoundManager.PlayRandomClip(creatureVoice, birdScreechSFX); WalkieTalkie.TransmitOneShotAudio(creatureVoice, birdScreechSFX[UnityEngine.Random.Range(0, birdScreechSFX.Length)]); RoundManager.Instance.PlayAudibleNoise(base.transform.position, 12f, 0.6f, 0, noiseIsInsideClosedShip: false, 911); } public void SetFlyDirection() { if (birdStunned) { Vector3 localEulerAngles = Body.localEulerAngles; localEulerAngles.x = 0f; localEulerAngles.z = 0f; Body.localEulerAngles = localEulerAngles; return; } bool flag = false; flag = averageVelocity * speedElevationMultiplier < 12f; float num = (Body.position - previousPosition).magnitude / Time.deltaTime; if (daytimeEnemyLeaving) { Body.rotation = Quaternion.Lerp(Body.rotation, Quaternion.LookRotation(Body.position - previousPosition, Vector3.up), 5f * Time.deltaTime); } else if (currentBehaviourStateIndex == 0 || timeSinceEnteringFlight < 1f) { flag = false; Body.rotation = Quaternion.Lerp(Body.rotation, Quaternion.Euler(new Vector3(0f, randomYRot, 0f)), 10f * Time.deltaTime); } else if (averageVelocity * speedElevationMultiplier > 0f) { Body.rotation = Quaternion.Lerp(Body.rotation, Quaternion.LookRotation(Body.position - previousPosition, Vector3.up), 5f * Time.deltaTime); } if (velocityInterval <= 0f) { velocityInterval = 0.1f; velocityAverageCount++; if (velocityAverageCount > 5) { averageVelocity += (num - averageVelocity) / 6f; } else { averageVelocity += num; if (velocityAverageCount == 5) { averageVelocity /= velocityAverageCount; } } } else { velocityInterval -= Time.deltaTime; } creatureAnimator.SetBool("flapping", flag); if (flag) { if (flappingAudio.volume <= 0.99f) { flappingAudio.volume = Mathf.Min(flappingAudio.volume + Time.deltaTime, 1f); } if (!flappingAudio.isPlaying) { flappingAudio.Play(); } } else if (flappingAudio.volume >= 0.05f) { flappingAudio.volume = Mathf.Max(flappingAudio.volume - Time.deltaTime, 0f); } else { flappingAudio.Stop(); } lerpedElevation = Mathf.Lerp(lerpedElevation, averageVelocity * speedElevationMultiplier / maxSpeed, Time.deltaTime * 0.5f); bodyAnimator.SetFloat("elevation", Mathf.Clamp(lerpedElevation * randomHeightOffset, 0.02f, 0.98f)); previousPosition = Body.position; } public override void HitEnemy(int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false) { base.HitEnemy(force, playerWhoHit, playHitSFX); if (base.IsOwner) { KillEnemyOnOwnerClient(); } } public override void KillEnemy(bool destroy = false) { base.KillEnemy(destroy); bodyAnimator.SetBool("stunned", value: true); creatureAnimator.SetBool("dead", value: true); } public override void OnSyncPositionFromServer(Vector3 newPos) { base.OnSyncPositionFromServer(newPos); if (!daytimeEnemyLeaving && !(timeSinceEnteringFlight < 4f) && currentBehaviourStateIndex == 0) { SwitchToBehaviourStateOnLocalClient(1); } } public override void AnimationEventA() { base.AnimationEventA(); if (base.IsServer && timeSinceSquawking > 0.7f && UnityEngine.Random.Range(0, 100) < birdNoisiness) { timeSinceSquawking = 0f; BirdScreechClientRpc(); } } [ClientRpc(Delivery = RpcDelivery.Unreliable)] public void BirdScreechClientRpc() { NetworkManager networkManager = base.NetworkManager; if ((object)networkManager != null && networkManager.IsListening) { if (__rpc_exec_stage != __RpcExecStage.Client && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams clientRpcParams = default(ClientRpcParams); FastBufferWriter bufferWriter = __beginSendClientRpc(2325720037u, clientRpcParams, RpcDelivery.Unreliable); __endSendClientRpc(ref bufferWriter, 2325720037u, clientRpcParams, RpcDelivery.Unreliable); } if (__rpc_exec_stage == __RpcExecStage.Client && (networkManager.IsClient || networkManager.IsHost)) { BirdScreech(); } } } public override void AnimationEventB() { base.AnimationEventB(); creatureSFX.PlayOneShot(birdHitGroundSFX); } protected override void __initializeVariables() { base.__initializeVariables(); } [RuntimeInitializeOnLoadMethod] internal static void InitializeRPCS_DoublewingAI() { NetworkManager.__rpc_func_table.Add(838150599u, __rpc_handler_838150599); NetworkManager.__rpc_func_table.Add(3264241129u, __rpc_handler_3264241129); NetworkManager.__rpc_func_table.Add(2325720037u, __rpc_handler_2325720037); } private static void __rpc_handler_838150599(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { NetworkManager networkManager = target.NetworkManager; if ((object)networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = __RpcExecStage.Server; ((DoublewingAI)target).AlertBirdServerRpc(); target.__rpc_exec_stage = __RpcExecStage.None; } } private static void __rpc_handler_3264241129(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { NetworkManager networkManager = target.NetworkManager; if ((object)networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = __RpcExecStage.Client; ((DoublewingAI)target).AlertBirdClientRpc(); target.__rpc_exec_stage = __RpcExecStage.None; } } private static void __rpc_handler_2325720037(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { NetworkManager networkManager = target.NetworkManager; if ((object)networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = __RpcExecStage.Client; ((DoublewingAI)target).BirdScreechClientRpc(); target.__rpc_exec_stage = __RpcExecStage.None; } } protected internal override string __getTypeName() { return "DoublewingAI"; } }