using System.Collections; using System.Collections.Generic; using NaughtyAttributes; using UnityEngine; [RequireComponent(typeof(Rigidbody2D))] public class Entity : MonoBehaviour { [SerializeField] [Required] protected GameFlowManager gameFlowManager = null!; [field: SerializeField] [field: Required] protected EntityStats stats { get; private set; } [field: SerializeField]public float Health {get; private set; } 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; [SerializeField]private float attackRange; [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; void Awake() => rb = GetComponent(); protected virtual void Start() { direction = new Vector3(1,0,0); attackTimer = attackCooldown; } protected virtual void Update() {} protected virtual void FixedUpdate() { //TODO sqrMagnitude? if (beingPushed && rb.velocity.magnitude < stats.MinVelocityWhenThrown) { rb.velocity = Vector2.zero; beingPushed = false; } } 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; if(Health <= 0){ isAlive = false; OnDied(); return false; } return true; } protected bool IsInAttackRange(){ return Vector2.Distance(transform.position, target.position) <= 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() {} }