using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Unity.VisualScripting; using UnityEngine; using UnityEngine.AI; using static EnemySpawnerData; [SerializeField] public class Enemy: AttackerAndDamageable { [Header("Mechanics Attributes")] [SerializeField] public float ChaseDistance = 10f; [SerializeField] public float ChaseDistanceBuffer = 1f; [SerializeField] public float AttackDistance = 1.5f; [SerializeField] public float AttackMaskDiameter = 1f; [Header("Enemy Attributes")] [SerializeField] public float Attack = 10f; [SerializeField] public float Speed = 5f; [SerializeField] public float Health = 10f; [SerializeField] public float Energy = 10f; protected FloatingTextSpawner TextPopUp; protected Player Player { get { return Player.Instance; } } protected Transform PlayerTransform { get { return Player.transform; } } protected Vector2 PlayerPos { get { return PlayerTransform.position; } } protected Vector2 CrystalPos { get { return GameManager.Crystal.transform.position; } } protected GameObject Owner; protected Rigidbody2D Rigidbody; protected Transform MyTransform { get { return Owner.transform; } } protected Vector2 MyPos { get { return MyTransform.position; } set { MyTransform.position = value; } } protected NavMeshAgent PathAgent; protected Material MaterialColorOverlay; protected bool IsUpdating; public float DistFromPlayer { get; protected set; } public float DistFromCrystal { get; protected set; } protected bool CanAttackPlayer => DistFromPlayer <= AttackDistance && CanAttack; protected bool CanAttackCrystal => DistFromCrystal <= AttackDistance && CanAttack; public bool AggroOnPlayer { get; protected set; } public bool AggroOnCrystal{ get; protected set; } public State CurrentState; public State PrevState; public enum State { None, GoToCrystal, AttackCrystal, ChasePlayer, AttackPlayer, PrepareAttack, FinalizeAttack, TakeDamage, Die } public Enemy(GameObject owner) { Owner = owner; PathAgent = Owner.GetComponent(); PathAgent.updatePosition = false; PathAgent.updateRotation = false; PathAgent.updateUpAxis = false; PathAgent.speed = Speed; IsUpdating = false; TextPopUp = new FloatingTextSpawner(Owner.transform, 1); OnTakeDamage += (damage, direction) => SetState(State.TakeDamage); OnDeath += () => SetState(State.Die); OnDeath += () => UnsubscribeToEvent(); Rigidbody = Owner.GetComponent(); foreach (var material in Owner.GetComponentsInChildren().Select(x => x.material).ToList()) { switch (material.name.Split(' ')[0]) { case "DamageFlashMat": MaterialColorOverlay = material; break; } } } private Action cachedUpdate; protected void SubscribeToEvent() { cachedUpdate = () => { if (PathAgent == null || Owner == null) return; PathAgentHandler.UpdatePositionIso(PathAgent, Owner.transform); Update(); }; EnemyManagers[Enemies.Gobler].UpdateTick += cachedUpdate; EnemyManagers[Enemies.Gobler].GizmoTick += OnDrawGizmos; } protected void UnsubscribeToEvent() { EnemyManagers[Enemies.Gobler].UpdateTick -= cachedUpdate; EnemyManagers[Enemies.Gobler].GizmoTick -= OnDrawGizmos; } protected virtual void SetPriorityState() { } protected virtual void DoUpdate() { } protected void Update() { if (Owner == null) return; if (GameManager.Crystal == null) return; if (IsUpdating) return; IsUpdating = true; DistFromPlayer = Vector2.Distance(MyPos, PlayerPos); DistFromCrystal = Vector2.Distance(MyPos, CrystalPos); SetPriorityState(); DoUpdate(); IsUpdating = false; } protected virtual void SetState(State newState) { } protected virtual void OnDrawGizmos() { } }