- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using MyCollections.AI.FinitStateMachine;
- using UnityEngine.UI;
- using MyCollections.DesignPatterns.Visitor;
- using System;
- [RequireComponent(typeof(Animator))]
- public abstract class NPCController : MonoBehaviour, IHealthSystem, INotifyObservers
- {
-
- [Header("NPC Attributes: ")]
- [SerializeField] protected string npcName;
- [SerializeField] protected int health;
- [SerializeField] protected int maxHealth;
-
- [Header("NPC Idle Settings: ")]
- public float timer = 0f;
- [SerializeField] protected float minIdleTime = 2f;
- [SerializeField] protected float maxIdleTime = 10f;
- [SerializeField] protected Vector2 lastDirection = Vector2.right;
-
- [Header("NPC Components: ")]
- [SerializeField] protected FSM fsm;
- [SerializeField] protected Agent agent;
- [SerializeField] protected Animator animator;
- [SerializeField] protected FOV agentFOV;
- [SerializeField] protected Image healthBarImage;
- [SerializeField] private GameObject healthDamageObject;
- [SerializeField] protected AudioSource audioSource;
- protected NPCManager npcManager;
- private bool isDead = false;
-
- protected List<IObserver> observers = new List<IObserver>();
-
- [SerializeField] protected List<string> observersNames = new List<string>();
-
- public event Action<NPCController> OnNPCDied = delegate { };
-
- public Agent Agent => agent;
- public Animator Animator => animator;
- public FOV AgentFOV => agentFOV;
- public int MaxHealth => maxHealth;
- public bool IsCoroutineRunning { get; set; }
- public NPCManager NPCManager => npcManager;
- public string NPCname => npcName;
- public Image HealthBarImage => healthBarImage;
- public Vector2 LastDirection
- {
- get => lastDirection;
- set => lastDirection = value;
- }
- public AudioSource AudioSource => audioSource;
- protected virtual void Awake()
- {
- if (!TryGetComponent(out agent))
- {
- Debug.LogError("Agent component not found on this GameObject!");
- }
- if (!TryGetComponent(out agentFOV))
- Debug.LogError($"{nameof(FOV)} component not found on this GameObject!");
- animator = GetComponent<Animator>();
- }
-
- protected virtual void Start()
- {
- npcManager = gameObject.GetComponentInParent<NPCManager>();
- foreach (IObserver observer in observers)
- {
- if (observer != null)
- {
- observersNames.Add(observer.ToString());
- }
- }
- }
-
- protected virtual void Update()
- {
-
- AnimationController();
- }
- protected virtual void OnEnable()
- {
- health = maxHealth;
- isDead = false;
- }
- protected virtual void OnDisable()
- {
-
- }
- protected virtual void AnimationController()
- {
- if (!agent.agentStop)
- {
- lastDirection = agent.agentVelocity.normalized;
- }
- animator.SetBool("IsStopped", agent.agentStop);
- animator.SetFloat("VelocityX", agent.agentVelocity.x);
- animator.SetFloat("VelocityY", agent.agentVelocity.y);
- animator.SetFloat("LookDirectionX", lastDirection.x);
- animator.SetFloat("LookDirectionY", lastDirection.y);
- }
-
- public void NotifyObservers(NotificationType type,params (string key, object value)[] parameters)
- {
- ObserverNotification notification = new ObserverNotification(type);
-
- foreach ((string key, object value) param in parameters)
- {
- notification.AddData(param.key, param.value);
- }
- foreach (IObserver observer in observers)
- {
- if (observer != null)
- {
- Debug.Log("Observer: " + observer.ToString());
- observer.OnNotify(notification);
- }
- else
- {
- Debug.Log("Observer is NULL: " + nameof(observer));
- }
- }
- }
- public virtual int CurrentHealth() => health;
- public virtual void Heal(int amount) => health += amount;
- public virtual bool IsDead()
- {
- if (health <= 0 && !isDead)
- {
- isDead = true;
- OnNPCDied.Invoke(this);
- return true;
- }
- return false;
- }
- public virtual void TakeDamage(int amount)
- {
- if (isDead) return;
- health -= amount;
- animator.SetFloat("DamageDirectionX", lastDirection.x);
- animator.SetFloat("DamageDirectionY", lastDirection.y);
-
- NotifyObservers(NotificationType.WorldUI, ("NPCController", this), ("DamageAmount", amount));
- IsDead();
- }
-
- public void SetIdleTime() => timer = UnityEngine.Random.Range(2f, maxIdleTime);
-
- public void AddObserver(IObserver observer)
- {
- if (!observers.Contains(observer))
- {
- observers.Add(observer);
- }
- }
- public void RemoveObserver(IObserver observer)
- {
- if (observers.Contains(observer))
- {
- observers.Remove(observer);
- }
- }
- }