Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / NPC / Orc / OrcNPCController.cs
using System.Collections;
using UnityEngine;
using MyCollections.AI.FinitStateMachine;
using System.Collections.Generic;
using TMPro;

public class OrcNPCController : EnemyNPCContoller
{
    [SerializeField] private int XpReward = 5;
    [SerializeField] private TextMeshProUGUI tmpName;
    [SerializeField] private State currentState;
    [SerializeField] private GameObject weapon;
    [SerializeField] private GameObject coin;

    [SerializeField] private float deadTimer = 2;
    [SerializeField] private float disabletimer;

    [Header("Character Combat Settings: ")]
    [SerializeField] private float attackTimer;
    [SerializeField] private float maxAttackTimer;
    [SerializeField] private float attackRange;
    [SerializeField] private int attackDamage;

    private Animator weaponAnimator;
    private Rigidbody2D rb;
    private SpriteRenderer sRenderer;

    public float AttackTimer => attackTimer;
    public float MaxAttackTimer => maxAttackTimer;
    public Animator WeaponAnimator => weaponAnimator;
    public GameObject Weapon => weapon;

    private bool isAttacking = false;
    public bool IsHurt { get; set; }

    protected override void Awake()
    {
        base.Awake();
        weaponAnimator = weapon.GetComponent<Animator>();
        weapon.SetActive(false);
        rb = GetComponent<Rigidbody2D>();
        sRenderer = GetComponent<SpriteRenderer>();
    }

    protected override void Start()
    {
        base.Start();
        tmpName.text = npcName;
        disabletimer = deadTimer;
    }

    protected override void OnEnable()
    {
        base.OnEnable();
        health = maxHealth;
        lastDirection = Vector2.right;
        AgentFOV.IsEnabled = true;
        attackTimer = MaxAttackTimer;
        rb.bodyType = RigidbodyType2D.Dynamic;
    }

    protected override void OnDisable()
    {
        base.OnDisable();
        disabletimer = deadTimer;
    }

    // Update is called once per frame
    protected override void Update()
    {
        base.Update();
    }

    protected void FixedUpdate()
    {
        if (isAttacking)
            PerformAttack();
    }
    protected override void AnimationController()
    {
        base.AnimationController();

        animator.SetBool("IsDead", health <= 0f);

        if (animator.GetBool("IsDead"))
        {
            AnimatorClipInfo deadClip = animator.GetCurrentAnimatorClipInfo(0)[0];
            float wait = deadClip.clip.length;
            disabletimer -= Time.deltaTime;
            
            if (disabletimer <= 0f)
            {
                gameObject.SetActive(false);
            }
        }

        if (weapon.activeSelf)
        {
            weaponAnimator.SetFloat("LookDirectionX", lastDirection.x);
            weaponAnimator.SetFloat("LookDirectionY", lastDirection.y);
        }

        if (isAttacking)
        {
            StartCoroutine(RecoverAttack());
        }
    }

    //Perform the attack on target
    private void PerformAttack()
    {
        if (agentFOV.GetTarget() != null)
        {
            Vector3 targetDir = agentFOV.TargetDirection;
            RaycastHit2D hit = Physics2D.Raycast(transform.position, targetDir, attackRange);
            Debug.DrawRay(transform.position, targetDir * hit.distance, Color.blue, 5f);

            // Check if the raycast hit something
            if (hit.collider != null)
            {
                // Check if the hit object has a health system component
                if (hit.collider.TryGetComponent(out IHealthSystem h))
                {
                    h.TakeDamage(attackDamage);
                }
            }
        }

        isAttacking = false;
    }

    //Set the attack
    //Using int as parameter since the unity Animation event don't support booleans
    public void SetAttack(int value) => isAttacking = value != 0;

    //Cooldown timer
    private IEnumerator RecoverAttack()
    {
        while (attackTimer >= 0f)
        {
            attackTimer -= Time.deltaTime;
            yield return null;
        }

        attackTimer = maxAttackTimer;
    }

    //Take damage
    public override void TakeDamage(int amount)
    {
        base.TakeDamage(amount);
        animator.SetTrigger("Hurt");    
    }

    //Animation Event
    //When the NPC get's it sprite changes color
    public void ChangeSpriteColor(string colorName)
    {
        switch (colorName)
        {
            case "white":
                sRenderer.color = Color.white;
                break;

            case "red":
                sRenderer.color = Color.red;
                break;
        }
    }

    //Checks if the chatacter is dead
    public override bool IsDead()
    {
        if (base.IsDead())
        {
            rb.bodyType = RigidbodyType2D.Kinematic;
            GameManager.Instance.GainExperience(XpReward);
            Instantiate(coin, transform.position, Quaternion.identity);
            return true;
        }

        return false;
    }

    public void OnGUI()
    {
        Rect rect = new Rect(0f, 0f, 300f, 200f); // Adjust size as needed
        GUI.color = Color.red;
        List<string> list = new List<string>();

        if (currentState != null)
        {
            list.Add(currentState.name);

            foreach (Transition t in currentState.GetTransitions())
            {
                list.Add($"Transition: {t.name}");
            }

            // Combine all strings into one string with line breaks
            string combinedText = string.Join("\n", list);

            // Create a GUIStyle to modify the text appearance
            GUIStyle style = new GUIStyle(GUI.skin.box);
            style.fontSize = 25; // Set the font size
            style.alignment = TextAnchor.MiddleCenter; // Center align the text (optional)

            // Display the combined string in the GUI.Box with the custom style
            GUI.Box(rect, combinedText, style);
        }
    }
}