using System.Collections; using System.Collections.Generic; using NaughtyAttributes; using UnityEngine; [RequireComponent(typeof(Rigidbody2D))] public class Entity : MonoBehaviour { [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; [SerializeField] private Transform target; public string entityName { get; protected set; } private Collider atkCollider; public Vector3 direction { get; set; } public Rigidbody2D rb { get; private set; } bool beingPushed; [SerializeField] GameObject halo; virtual protected void Awake() => rb = GetComponent(); 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); } } public void SetTarget(Transform newTarget) { target = newTarget; } public Transform GetTarget() { return target; } //Apply damage to the entity, returns true if it is still alive public virtual bool TakeDamage(float amount) { Health -= amount; healthBar.SetHealthFraction(Health / initialHealth); if (Health <= 0) { isAlive = false; 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 void AddImpulse(Vector3 impulse) { beingPushed = true; rb.AddForce(impulse, ForceMode2D.Impulse); } protected virtual void OnDied() { } public void EnableHalo() { halo.SetActive(true); } public void DisableHalo() { halo.SetActive(false); } }