using System; using System.Collections; using System.Collections.Generic; using JetBrains.Annotations; using NaughtyAttributes; using UnityEngine; [RequireComponent(typeof(Rigidbody2D))] public class Entity : MonoBehaviour { [Flags] public enum EntityFlag { Vampire = 0, Monster = 1, Gladiator = 2, } public Arena arena = null!; [SerializeField] [Required] public GameFlowManager gameFlowManager = null!; [field: SerializeField] public float Health { get; private set; } [Min(10f)] protected float initialHealth; [SerializeField] [Required] protected HealthBar healthBar; bool isAlive = true; public int bloodTokens = 1; [field: SerializeField] public float movementSpeed { get; private set; } [field: SerializeField] public float rotSpeed { get; private set; } [SerializeField] private float fov; [field: SerializeField] public float attackRange { get; private set; } [field: SerializeField] public float attackDmg { get; private set; } [SerializeField] protected float attackCooldown; protected float attackTimer; public Transform target; public EntityFlag entityType { get; protected set; } public Vector3 direction { get; set; } public Rigidbody2D rb { get; private set; } public Collider2D collider { get; private set; } public SpriteRenderer renderer { get; private set; } [SerializeField] GameObject halo; [SerializeField] Color deadColor = Color.red; [SerializeField] Color emptyColor = Color.grey; [HideInInspector] public Animator animator; virtual protected void Awake(){ rb = GetComponent(); collider = GetComponent(); renderer = GetComponent(); animator = GetComponentInChildren(); } protected virtual void Start() { if (direction == Vector3.zero && !(this is VampireEntity)) Debug.LogWarning("Entity had null direction."); attackTimer = attackCooldown; initialHealth = Health; if (halo != null) { halo.SetActive(false); } } protected virtual void Update() { } protected virtual void FixedUpdate() {} protected virtual void Attack() { } protected virtual void SpecialAttack() { } protected virtual void MoveToTarget() { //Would be nice if we could force this to be in FixedUpdate direction = Vector3.RotateTowards(direction, (target.position - transform.position), rotSpeed * Time.fixedDeltaTime, 0.0f); if (!IsInAttackRange()) { rb.MovePosition(transform.position + direction * movementSpeed * Time.fixedDeltaTime); } } //Apply damage to the entity, returns true if it is still alive public virtual bool TakeDamage(float amount, Entity other) { Health -= amount; healthBar.SetHealthFraction(Health / initialHealth); if (Health <= 0) { OnDied(); return false; } return true; } public virtual void HealDamage(float amount) { Health += amount; healthBar.SetHealthFraction(Health / initialHealth); if(Health > initialHealth) { Health = initialHealth; } } protected bool IsInAttackRange() { float distance = Vector2.Distance(transform.position, target.position); return distance <= attackRange; } protected bool IsLookingAtTarget() { float angle = Vector2.SignedAngle(direction, (target.position - transform.position)); return angle >= -fov && angle <= fov; } public bool IsAlive() { return isAlive; } protected virtual void OnDied() { isAlive = false; if(!(collider is null)){ collider.isTrigger = true; } if(!(rb is null)){ rb.isKinematic = true; rb.velocity = Vector2.zero; } healthBar.gameObject.SetActive(false); if(bloodTokens > 0){ renderer.color = deadColor; renderer.sortingOrder = -1; }else{ renderer.color = emptyColor; renderer.sortingOrder = -2; } } protected virtual void OnEmpty(){ renderer.color = emptyColor; renderer.sortingOrder = -2; } public void EnableHalo() { halo.SetActive(true); } public void DisableHalo() { halo.SetActive(false); } }