using System.Collections; using System.Collections.Generic; using UnityEngine; using Assets.FantasyMonsters.Scripts; using System.Runtime.CompilerServices; using Assets.Scripts.CharacterScripts; using UnityEngine.EventSystems; using System; using UnityEngine.Analytics; using Unity.VisualScripting; using UnityEngine.SceneManagement; public class EnemyController : MonoBehaviour{ private Monster Monster; // A reference to the Monster script; this enemy's animations public int health; // Enemy health public float moveSpeed = 5f, chaseMultiplier = 1.5f; // How fast the player moves left and right and the chase multiplier to the speed public float jumpForce = 25f; // How fast/far the player jumps in the air Rigidbody2D rb; // The enemy's rigidbody public int damage = 10; // The enemy's damage public int experience = 10; // The enemy's experience (that it gives upon death) public bool isDead = false; // Boolean to see if the enemy died public float patrolOffset; // The offset for moving left and right public Vector3 beginningPosition; // Enemy start position private Vector2 leftTarget, rightTarget, currentTarget; // The waypoints to patrol private bool leftReached = false, rightReached = true; // See if we reached the left/right waypoint; just initializing them as opposites public Vector3 faceRight, faceLeft; // Vector for the sprite facing right and left; set it per enemy public Transform player; // Reference to the player Vector2 chaseDirection; // The direction the enemy will chase the player public float detectionRange; // Range that the enemy detects the player within private bool isChasing = false; // Boolean to see if the enemy is chasing the player or not public bool ableToJump = false; // Undecided if I want certain enemies to jump or not yet public float attackRange; // Attack range for the enemy, set per enemy public BossHealthBar bossHealthBar; // Reference to the boss health bar if this enemy is the boss public AudioSource enemySound; // The sound effect for this enemy // Start is called before the first frame update void Start(){ // If the boss health bar is not null, set the health if (bossHealthBar != null){ bossHealthBar.SetBossMaxHealth(health); } // Get the monster's components for animations Monster = GetComponent(); // Set the monster's state to ready Monster.SetState(MonsterState.Ready); rb = GetComponent(); // This locks the Z-axis, prevents the player sprite from falling over unintentionally due to physics rb.constraints = RigidbodyConstraints2D.FreezeRotation; // Save the starting position for the enemy and initialize the reference to the player's transform beginningPosition = transform.position; player = GameObject.FindGameObjectWithTag("Player").transform; } // Update is called once per frame void Update(){ // Calculate the distance to the player, and see if the player is within the detection range float distToPlayer = Math.Abs(Vector2.Distance(transform.position, player.position)); if (distToPlayer <= detectionRange){ // Set isChasing to true isChasing = true; // If so, begin to chase Chase(distToPlayer); } else if (distToPlayer > detectionRange){ if (isChasing){ // This allows the enemy to move back to its patrol zone after a chase isChasing = false; rightReached = true; transform.position = Vector2.MoveTowards(transform.position, leftTarget, moveSpeed * Time.deltaTime); } // Patrol the corresponding zone Patrol(); } } void Patrol(){ Monster.SetState(MonsterState.Walk); // Set the waypoints on the left and the right to patrol leftTarget = new Vector2(beginningPosition.x - patrolOffset, beginningPosition.y); rightTarget = new Vector2(beginningPosition.x + patrolOffset, beginningPosition.y); Vector2 moveDirection = new Vector2(); // If we reached the right, move towards the left if (rightReached){ moveDirection = (leftTarget - rb.position).normalized; currentTarget = leftTarget; transform.position = Vector2.MoveTowards(transform.position, leftTarget, moveSpeed * Time.deltaTime); } else if (leftReached){ // If we reached the left, move towards the right moveDirection = (rightTarget - rb.position).normalized; currentTarget = rightTarget; transform.position = Vector2.MoveTowards(transform.position, rightTarget, moveSpeed * Time.deltaTime); } // If we move right, face right; if we move left, face left if (moveDirection.x > 0f){ transform.localScale = faceRight; } else if (moveDirection.x < 0f){ transform.localScale = faceLeft; } // If we're within 1f from our position to the waypoint we are seeing if (Vector2.Distance(transform.position, currentTarget) < 1f){ // If we previously reached the right, now we reached the left if (rightReached){ rightReached = false; leftReached = true; // Same but the opposite logic } else if (leftReached){ leftReached = false; rightReached = true; } } } void Chase(float distToPlayer){ Monster.SetState(MonsterState.Run); // Calculate the direction the enemy is chasing chaseDirection = (player.position - transform.position).normalized; rb.velocity = chaseDirection * moveSpeed; // Take into account the way the sprite is facing if (chaseDirection.x > 0f){ transform.localScale = faceRight; } else if (chaseDirection.x < 0f){ transform.localScale = faceLeft; } // Chase the player at a speed meant to be faster than the parol speed transform.position = Vector2.MoveTowards(transform.position, new Vector2(player.position.x, beginningPosition.y), moveSpeed * 1.5f * Time.deltaTime); leftReached = false; rightReached = false; // If we're within range of the player, play attack animation if (distToPlayer <= attackRange){ Monster.Attack(); } } // Apply damage to the enemy public void TakeDamage(int damage){ health -= damage; // If the health drops to/below 0, destroy the enemy and mark isDead if (health <= 0){ // If this is the boss that is dying, do the same process but load the you win scene if (bossHealthBar != null){ isDead = true; player.GetComponent().GainExp(experience); Destroy(gameObject); SceneManager.LoadScene("YouWin"); } isDead = true; player.GetComponent().GainExp(experience); Destroy(gameObject); } // If the boss is taking damage, adjust the health bar as needed if (bossHealthBar != null){ bossHealthBar.SetBossHealth(health); } } void OnCollisionEnter2D(Collision2D other){ // If the enemy collides with the player's weapon, then take the corresponding player's damage if (other.gameObject.CompareTag("PlayerWeapon")){ WeaponController playerWeapon = other.gameObject.GetComponent(); if (playerWeapon.playerAttacks){ // Play this enemy's sound effect if hit enemySound.Play(); TakeDamage(playerWeapon.damage); } } else if (other.gameObject.CompareTag("Enemy")){ // Ignore collisions with other enemies Physics2D.IgnoreCollision(GetComponent(), other.collider, true); } else if (other.gameObject.CompareTag("EnemyWeapon")){ // Ignore the enemy weapon if it exists Physics2D.IgnoreCollision(GetComponent(), other.collider, true); } } }