Skip to content
Snippets Groups Projects
Fighter.cs 5.24 KiB
Newer Older
  • Learn to ignore specific revisions
  • using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public interface IFighterCallback
    {
    
        void OnFighterDeath(Fighter fighter);
    
    }
    
    // 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, IRoundCallback
    
    {
    
        [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 maxHealth = 100; // Dynamically valculated based on upgrades
    
        [SerializeField] protected int currentHealth = 100;
    
        protected float currentHealthPercentage { get => (float) currentHealth / maxHealth; }
    
        protected Animator animator;
    
        protected new Rigidbody2D rigidbody;
    
        protected new BoxCollider2D collider;
    
        protected SpriteRenderer spriteRenderer;
    
        protected HealthBarController healthBarController;
    
        protected bool alive { get => currentHealth > 0; }
    
        protected bool roundRunning = false;
    
        protected FighterTypes fighterType;
    
        protected string opponentTag;
    
        protected Vector3 initalScale;
        protected Vector3 initalPosition;
    
        protected int initialLayer;
    
        protected Sprite initialSprite;
    
        protected abstract bool CanAttack();
    
        protected abstract void Attack();
    
    
        float timeSinceLastAttack = float.PositiveInfinity;
    
    
        protected virtual void Awake()
        {
            animator = GetComponent<Animator>();
    
            rigidbody = GetComponent<Rigidbody2D>();
    
            collider = GetComponent<BoxCollider2D>();
    
            spriteRenderer = GetComponent<SpriteRenderer>();
    
    Moritz Meyerhof's avatar
    Moritz Meyerhof committed
            healthBarController = GetComponentInChildren<HealthBarController>();
    
            fighterType = FighterTypes.ENEMY;
    
            initalPosition = transform.position;
            initalScale = transform.localScale;
    
            initialLayer = gameObject.layer;
    
            initialSprite = spriteRenderer.sprite;
    
        }
    
        protected virtual void Start()
        {
    
            RoundController.instance.roundCallbacks.Add(this);
            OnRoundEnd();
    
        }
    
        protected virtual void Update()
        {
            if (alive)
            {
    
                    timeSinceLastAttack += Time.deltaTime;
                    var timeUntilNextAttack = baseAttackSpeed - timeSinceLastAttack;
                    if (timeUntilNextAttack <= 0)
                    {
                        Attack();
                        timeSinceLastAttack = float.IsInfinity(timeUntilNextAttack) ? 0 : -timeUntilNextAttack; // To account for overshoot
                    }
                }
                else
                {
                    timeSinceLastAttack = float.PositiveInfinity;
    
        public virtual int DealDamage(int dmg)
    
            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.OnFighterDeath(this));
    
                // Disable own collision so that other Fighters can run over our dead body
                gameObject.layer = LayerMask.NameToLayer("Ground-Only Collision");
    
                healthBarController.SetHealthBarEnabled(false);
    
            }
            else
            {
                animator.SetTrigger("Hurt");
    
                healthBarController.ShowHealth(currentHealthPercentage);
    
        protected FighterStats GetStats()
        {
            return StatsManager.instance.fighterStats[fighterType];
        }
    
    
        void OnTriggerEnter2D(Collider2D other)
        {
    
    #if false
            Debug.Log(string.Format("'{0}' (tag '{1}') collided with '{2}' (tag '{3}') in parent '{4}' (tag '{5}')", name, tag, other.name, other.tag, other.transform.parent ? other.transform.parent.name : null, other.transform.parent ? other.transform.parent.tag : null));
    #endif
            if (other.CompareTag(opponentTag))
    
                var damageToDeal = Mathf.RoundToInt(baseAttackDamage * GetStats().damageMultiplier);
    
                other.GetComponent<Fighter>().DealDamage(damageToDeal);
            }
        }
    
    
        public virtual void OnRoundStart()
        {
            roundRunning = true;
            animator.enabled = true;
            collider.enabled = true;
            rigidbody.bodyType = RigidbodyType2D.Dynamic;
    
            maxHealth = currentHealth = Mathf.RoundToInt(baseHealth * GetStats().healthMultiplier);
    
            animator.Play("Idle");
    
            healthBarController.Reset();
    
        }
    
        public virtual void OnRoundEnd()
        {
            roundRunning = false;
            animator.enabled = false;
            timeSinceLastAttack = float.PositiveInfinity;
            collider.enabled = false;
            rigidbody.bodyType = RigidbodyType2D.Kinematic;
            rigidbody.velocity = Vector2.zero;
            rigidbody.MovePosition(initalPosition);
            transform.localScale = initalScale;
    
            gameObject.layer = initialLayer;
    
            spriteRenderer.sprite = initialSprite;
            callbacks.Clear();
    
            healthBarController.SetHealthBarEnabled(false);