using System.Collections; using System.Collections.Generic; using UnityEngine; public class AntiPlayer : Fighter, IFighterCallback { [SerializeField, Tooltip("How close the AntiPlayer has to be to start attacking, or how far away it has to be to start running towards the target")] float maxDistanceToEnemy = 1f; [SerializeField] float movementSpeed = 4f; [SerializeField, Tooltip("After killing an Enemy, how long to stay idle before targeting the next enemy")] float delayUntilNextTarget = 0.3f; string[] attackAnimationTriggers = new string[] { "Attack1", "Attack2", "Attack3" }; List<Fighter> enemies = new List<Fighter>(); Fighter currentTargetEnemy; protected override void Awake() { base.Awake(); fighterType = FighterTypes.ANTI_PLAYER; opponentTag = "Enemy"; animator.SetBool("Grounded", true); } protected override void Update() { base.Update(); if (!alive || currentTargetEnemy == null) { return; } var vectorToNextEnemy = currentTargetEnemy.transform.position - transform.position; var scale = transform.localScale; // Always face the target Enemy scale.x = vectorToNextEnemy.x < 0 ? -initalScale.x : initalScale.x; transform.localScale = scale; // Run towards target enemy if too far away if (Mathf.Abs(vectorToNextEnemy.x) > maxDistanceToEnemy) { animator.SetInteger("AnimState", 1); // Run rigidbody.velocity = new Vector2(Mathf.Sign(vectorToNextEnemy.x) * movementSpeed, rigidbody.velocity.y); } else { animator.SetInteger("AnimState", 0); rigidbody.velocity = new Vector2(0, rigidbody.velocity.y); } } protected override bool CanAttack() { if (currentTargetEnemy == null) { return false; } // Can only attack when near an Enemy var vectorToNextEnemy = currentTargetEnemy.transform.position - transform.position; return Mathf.Abs(vectorToNextEnemy.x) <= maxDistanceToEnemy; } protected override void Attack() { animator.SetTrigger(attackAnimationTriggers[Random.Range(0, attackAnimationTriggers.Length)]); } void CalculateClosestEnemy() { enemies.Sort((a, b) => (int)Mathf.Sign(Vector3.Distance(transform.position, a.transform.position) - Vector3.Distance(transform.position, b.transform.position))); currentTargetEnemy = enemies.Count > 0 ? enemies[0] : null; } public override int DealDamage(int dmg) { var actualDamage = base.DealDamage(dmg); StatsManager.instance.ModifyMana((int)(actualDamage * StatsManager.instance.manaReceiveMultiplier)); return actualDamage; } public void OnFighterDeath(Fighter fighter) { enemies.Remove(fighter); // Wait a short time before targeting next enemy. This is to avoid interrupting the current // attack animation, which would happen if we immediately ran to the next target. currentTargetEnemy = null; Invoke(nameof(CalculateClosestEnemy), delayUntilNextTarget); } public override void OnRoundStart() { base.OnRoundStart(); foreach (var enemy in GameObject.FindGameObjectsWithTag("Enemy")) { var fighter = enemy.GetComponent<Fighter>(); fighter.callbacks.Add(this); enemies.Add(fighter); } CalculateClosestEnemy(); } public override void OnRoundEnd() { base.OnRoundEnd(); enemies.Clear(); currentTargetEnemy = null; } }