using System.Collections.Generic;
using ActionGameFramework.Health;
using ActionGameFramework.Helpers;
using ActionGameFramework.Projectiles;
using Core.Utilities;
using TowerDefense.Affectors;
using TowerDefense.Level;
using UnityEngine;
using UnityEngine.Events;
namespace TowerDefense.Towers.TowerLaunchers
{
///
/// Rapid fire launcher, launchers a homing projectile
///
public class SuperTowerLauncher : HomingLauncher
{
///
/// How long the tower will stay active
///
public float towerLifeSpan = 10;
///
/// Angle, in degrees, to rotate, on the x axis, the fire vector by
///
public float fireVectorXRotationAdjustment = 45.0f;
///
/// Fires when the max amount of projectiles has been reached
///
public UnityEvent death;
///
/// Timer to invoke a unity event when it elapses
///
protected Timer m_LifeTimer;
///
/// Finds a random enemy in a list and fires from a random point
///
///
/// The list of enemies to sample from
///
///
/// The object used to attack
///
///
public override void Launch(List enemies, GameObject attack, Transform[] firingPoints,int maxAttack = 1)
{
var poolable = Poolable.TryGetPoolable(attack);
if (poolable == null)
{
return;
}
Targetable enemy = enemies[Random.Range(0, enemies.Count)];
Transform firingPoint = GetRandomTransform(firingPoints);
Launch(enemy, poolable.gameObject, firingPoint);
}
public override void Launch(Targetable enemy, GameObject attack, Transform firingPoint,int idx = 0)
{
var homingMissile = attack.GetComponent();
if (homingMissile == null)
{
Debug.LogError("No HomingLinearProjectile attached to attack object");
return;
}
Vector3 startingPoint = firingPoint.position;
Vector3 targetPoint = Ballistics.CalculateLinearLeadingTargetPoint(
startingPoint, enemy.position,
enemy.velocity, homingMissile.startSpeed,
homingMissile.acceleration);
homingMissile.SetHomingTarget(enemy);
var attackAffector = GetComponent();
Vector3 direction = attackAffector.towerTargetter.turret.forward;
Vector3 binormal = Vector3.Cross(direction, Vector3.up);
Quaternion rotation = Quaternion.AngleAxis(fireVectorXRotationAdjustment, binormal);
Vector3 adjustedFireVector = rotation * direction;
homingMissile.FireInDirection(startingPoint, adjustedFireVector);
PlayParticles(fireParticleSystem, startingPoint, targetPoint);
}
///
/// Subscribes to Level Manager onStateChanged
/// If waves have already begun, then begin death timer
///
protected virtual void OnEnable()
{
if (!LevelManager.instanceExists)
{
return;
}
LevelState currentState = LevelManager.instance.levelState;
if (currentState == LevelState.SpawningEnemies || currentState == LevelState.AllEnemiesSpawned)
{
m_LifeTimer = new Timer(towerLifeSpan, OnLifeTimerElapsed);
}
else
{
LevelManager.instance.levelStateChanged += OnLevelStateChanged;
}
}
///
/// Unsubscribe from Level Manager onStateChanged
///
protected virtual void OnDisable()
{
if (LevelManager.instanceExists)
{
LevelManager.instance.levelStateChanged -= OnLevelStateChanged;
}
}
///
/// Tick the timer
///
protected void Update()
{
if (m_LifeTimer == null)
{
return;
}
m_LifeTimer.Tick(Time.deltaTime);
}
///
/// Invoke the UnityEvent once the timer elapses
///
protected void OnLifeTimerElapsed()
{
death.Invoke();
}
///
/// Checks the current state, if within a valid state, start the death timer
///
///
/// The previous state the the LevelManager was in
///
///
/// The current state the LevelManager was in
///
void OnLevelStateChanged(LevelState previousState, LevelState currentState)
{
if (currentState == LevelState.SpawningEnemies || currentState == LevelState.AllEnemiesSpawned)
{
m_LifeTimer = new Timer(towerLifeSpan, OnLifeTimerElapsed);
}
}
}
}