using System.Collections; using System.Collections.Generic; using UnityEngine; using MyCollections.AI.FinitStateMachine; [RequireComponent(typeof(Animator))] public abstract class NPCConroller : MonoBehaviour, IHealthSystem { [Header("NPC Attributes: ")] [SerializeField] protected float health; [SerializeField] protected float maxHealth; [SerializeField] protected FSM fsm; [SerializeField] protected Agent agent; protected Animator animator; protected FOV agentFOV; protected List<IObserver> observers = new List<IObserver>(); public Agent Agent => agent; public Animator Animator => animator; public FOV AgentFOV => agentFOV; public float MaxHealth => maxHealth; public bool IsCoroutineRunning { get; set; } 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>(); } // Start is called before the first frame update protected virtual void Start() { if (fsm != null) fsm.SetUp(this); } // Update is called once per frame protected virtual void Update() { if (fsm != null) fsm.GUpdate(); AnimationController(); } protected virtual void AnimationController() { } protected void NotifyObservers() { foreach (IObserver observer in observers) { observer.OnNotify(this); // Notify each observer, passing the NPCController as the object } } public virtual float CurrentHealth() => health; public virtual void Heal(float ammount) => health += ammount; public virtual bool IsDead() => health <= 0f; public virtual void TakeDamage(float ammount) { health -= ammount; NotifyObservers(); } // Observer pattern methods public void AddObserver(IObserver observer) { if (!observers.Contains(observer)) { observers.Add(observer); } } public void RemoveObserver(IObserver observer) { if (observers.Contains(observer)) { observers.Remove(observer); } } }