using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;
public class Ally : MonoBehaviour
{
public static List<GameObject> troops = new List<GameObject>();
[Header("Stats")]
public float health;
[Header("Attacking")]
public bool hasRamDamage;
public float ramDamage;
public float ramKnockback;
[Space]
public bool hasMeleeAttacks;
public float meleeRange;
public float recoveryTime;
public float chargeTime;
public float meleeDamage;
public float meleeKnockback;
public GameObject attackObject;
[Space]
public bool hasRangedAttacks;
public float aimTime;
public float rangedRange;
public float rangedDamage;
public float rangedKnockback;
public float reloadTime;
public float projectileSpeed;
public GameObject projectile;
[Space]
public bool meleeReady = true;
public bool rangedReady = true;
public bool isAttacking;
[Space]
public float attackRadius;
public float forgetRadius;
[Header("Values")]
public float distanceBetweenTarget;
public GameObject currentTarget;
public float startingSpeed;
public float barTime;
[Header("References")]
public Slider slider;
public Animator anim;
public GameObject eyes;
public Barracks parent;
public Rigidbody2D rb;
public GameObject pivot;
public GameObject eyesPoint;
public GameObject forward;
public SpriteRenderer spriteRenderer;
public NavMeshAgent agent;
public GameObject damageNumber;
private Color startingColor;
private void Awake()
{
troops.Add(this.gameObject);
parent = GetComponentInParent<Barracks>();
parent.aliveAllies.Add(this.gameObject);
}
private void Start()
{
slider.maxValue = health;
agent.updateRotation = false;
agent.updateUpAxis = false;
startingColor = spriteRenderer.color;
startingSpeed = agent.speed;
StartCoroutine(UpdateClosestEnemy());
}
private void Update()
{
barTime -= Time.deltaTime;
slider.value = health;
if (Settings.instance.healthBarsSize == 2)
{
slider.transform.localScale *= 2;
}
if (barTime <= 0)
{
slider.gameObject.SetActive(false);
}
else
{
slider.gameObject.SetActive(true);
}
if (currentTarget != null)
{
var offset = 0f;
Vector2 direction = currentTarget.transform.position - transform.position;
direction.Normalize();
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
pivot.transform.rotation = Quaternion.Euler(Vector3.forward * (angle + offset));
}
HandleTargetting();
HandleAttacking();
Vector3 vel = transform.position * rb.velocity;
if (agent.velocity.x < 0)
{
spriteRenderer.flipX = true;
}
else if(agent.velocity.x >= 0)
{
spriteRenderer.flipX = false;
}
if (agent.velocity.magnitude > 0.1f)
{
eyes.transform.position = new Vector3(eyesPoint.transform.position.x, eyesPoint.transform.position.y, -4f);
//anim.SetBool("isMoving", true);
}
else
{
//anim.SetBool("isMoving", false);
eyes.transform.position = new Vector3(pivot.transform.position.x, pivot.transform.position.y, -4f);
}
}
IEnumerator UpdateClosestEnemy()
{
distanceBetweenTarget = Vector2.Distance(gameObject.transform.position, GetClosestEnemy().position);
currentTarget = GetClosestEnemy().gameObject;
yield return new WaitForSeconds(1);
StartCoroutine(UpdateClosestEnemy());
}
public void HandleTargetting()
{
Vector2 randomPoint = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y) + Random.insideUnitCircle * 3f;
if (distanceBetweenTarget < attackRadius & Enemy.enemies.Count > 0)
{
agent.SetDestination(GetClosestEnemy().transform.position);
}
else if (distanceBetweenTarget > forgetRadius)
{
agent.SetDestination(randomPoint);
}
}
public Transform GetClosestEnemy()
{
float minDistance = 9999;
GameObject target = null;
for (int i = 0; i < Enemy.enemies.Count; i++)
{
Transform targetTransform = Enemy.enemies[i].transform;
float distance = Vector2.Distance(gameObject.transform.position, targetTransform.position);
if (distance < minDistance)
{
minDistance = distance;
target = Enemy.enemies[i].gameObject;
Debug.Log(target);
}
}
if (target != null)
{
return target.transform;
}
else
{
return gameObject.transform;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (hasRamDamage == true)
{
if (collision.gameObject.CompareTag("Enemy"))
{
collision.gameObject.GetComponent<Rigidbody2D>().AddForce(forward.gameObject.transform.right * ramKnockback * 15, ForceMode2D.Impulse);
collision.gameObject.GetComponent<Enemy>().TakeDamage(ramDamage, 3, 1);
rb.AddForce(-forward.gameObject.transform.right * ramKnockback * 10, ForceMode2D.Impulse);
}
}
}
void HandleAttacking()
{
if (currentTarget != gameObject)
{
if (hasMeleeAttacks & distanceBetweenTarget < meleeRange & !isAttacking & meleeReady)
{
isAttacking = true;
meleeReady = false;
StartCoroutine(MeleeAttack());
}
if (hasRangedAttacks & distanceBetweenTarget < rangedRange & !isAttacking & rangedReady)
{
isAttacking = true;
rangedReady = false;
StartCoroutine(RangedAttack());
}
}
}
IEnumerator MeleeAttack()
{
spriteRenderer.color = Color.grey;
agent.speed /= 1.5f;
yield return new WaitForSeconds(chargeTime);
GameObject attack = Instantiate(attackObject, forward.transform.position, forward.transform.rotation);
PlayerMeleeAttack a = attack.GetComponent<PlayerMeleeAttack>();
a.damage = meleeDamage;
a.knockback = meleeKnockback;
a.type = 3;
isAttacking = false;
spriteRenderer.color = startingColor;
agent.speed = startingSpeed;
StartCoroutine(RecoverFromMelee());
}
IEnumerator RecoverFromMelee()
{
yield return new WaitForSeconds(recoveryTime);
meleeReady = true;
}
IEnumerator RangedAttack()
{
spriteRenderer.color = Color.gray;
agent.speed /= 3;
yield return new WaitForSeconds(aimTime);
GameObject Projectile = Instantiate(projectile, forward.transform.position, forward.transform.rotation);
Projectile p = Projectile.GetComponent<Projectile>();
p.speed = projectileSpeed;
p.damage = rangedDamage;
p.knockback = rangedKnockback;
p.type = 3;
isAttacking = false;
agent.speed = startingSpeed;
spriteRenderer.color = startingColor;
StartCoroutine(RecoverFromRanged());
}
IEnumerator RecoverFromRanged()
{
yield return new WaitForSeconds(reloadTime);
rangedReady = true;
}
public void TakeDamage(float damage, int strength)
{
barTime = 3;
health -= damage;
if (Settings.instance.damageNumbersSize != 3)
{
DamageNumber damagenumber = Instantiate(damageNumber, transform.position, transform.rotation).GetComponent<DamageNumber>();
damagenumber.Setup(damage, strength);
}
if (!isAttacking)
{
StartCoroutine(Flash());
}
if (health <= 0)
{
Die();
}
}
private void OnDestroy()
{
troops.Remove(this.gameObject);
Destroy(gameObject);
}
void Die()
{
troops.Remove(this.gameObject);
parent.aliveAllies.Remove(this.gameObject);
Destroy(gameObject);
}
IEnumerator Flash()
{
spriteRenderer.color = Color.red;
yield return new WaitForSeconds(0.1f);
spriteRenderer.color = startingColor;
}
}