using System.Collections; using System.Collections.Generic; using UnityEngine; public interface IFighterCallback { void OnDeath(); } // Generic subclass for any Fighter on the field, whether it's an Enemy or the AntiPlayer. // Contains stats management such as health, attacks, damage, death, etc. public abstract class Fighter : MonoBehaviour { [SerializeField] int baseHealth = 100; [SerializeField, Tooltip("Attack every x seconds")] float baseAttackSpeed = 1f; [SerializeField] int baseAttackDamage = 10; [SerializeField] int baseArmor = 1; public List<IFighterCallback> callbacks = new List<IFighterCallback>(); [SerializeField] protected int currentHealth = 100; protected Animator animator; protected bool alive { get => currentHealth > 0; } protected FighterTypes fighterType; protected abstract void Attack(); float timeSinceLastAttack = 0f; protected virtual void Awake() { animator = GetComponent<Animator>(); fighterType = FighterTypes.ENEMY; } protected virtual void Start() { currentHealth = Mathf.RoundToInt(baseHealth * GetStats().healthMultiplier); } protected virtual void Update() { if (alive) { timeSinceLastAttack += Time.deltaTime; var timeUntilNextAttack = baseAttackSpeed - timeSinceLastAttack; if (timeUntilNextAttack <= 0) // TODO only attack when near opposing faction { Attack(); timeSinceLastAttack = -timeUntilNextAttack; // To account for overshoot } } } public void DealDamage(int dmg) { if (!alive) { return; } var actualDamage = Mathf.Max(0, Mathf.RoundToInt(dmg - baseArmor * GetStats().armorMultiplier)); currentHealth = Mathf.Max(currentHealth - actualDamage, 0); if (currentHealth == 0) { animator.SetTrigger("Death"); callbacks.ForEach(c => c.OnDeath()); // TODO (Depending on the death animation) only destroy on round end so that corpses stay on the ground // Destroy(gameObject); } else { animator.SetTrigger("Hurt"); } } protected FighterStats GetStats() { return StatsManager.instance.fighterStats[fighterType]; } void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("AntiPlayer")) { var damageToDeal = Mathf.RoundToInt(baseAttackDamage * GetStats().damageMultiplier); other.GetComponent<Fighter>().DealDamage(damageToDeal); } } }