using Core.Health;
using TowerDefense.Affectors;
using TowerDefense.Towers;
using UnityEngine;
namespace TowerDefense.Agents
{
///
/// An implementation of Agent that will attack
/// any Towers that block its path
///
public class AttackingAgent : Agent
{
///
/// Tower to target
///
protected Tower m_TargetTower;
///
/// The attached attack affector
///
protected AttackAffector m_AttackAffector;
///
/// Is this agent currently engaging a tower?
///
protected bool m_IsAttacking;
public override void Initialize()
{
base.Initialize();
// Attack affector
m_AttackAffector.Initialize(configuration.alignmentProvider);
// We don't want agents to attack towers until their path is blocked,
// so disable m_AttackAffector until it is needed
m_AttackAffector.enabled = false;
}
///
/// Unsubscribes from tracked towers removed event
/// and disables the attached attack affector
///
public override void Remove()
{
base.Remove();
if (m_TargetTower != null)
{
m_TargetTower.removed -= OnTargetTowerDestroyed;
}
m_AttackAffector.enabled = false;
m_TargetTower = null;
}
///
/// Gets the closest tower to the agent
///
/// The closest tower
protected Tower GetClosestTower()
{
var towerController = m_AttackAffector.towerTargetter.GetTarget( -1 ) as Tower;
return towerController;
}
///
/// Caches the Attack Affector if necessary
///
protected override void LazyLoad()
{
base.LazyLoad();
if (m_AttackAffector == null)
{
m_AttackAffector = GetComponent();
}
}
///
/// If the tower is destroyed while other agents attack it, ensure it becomes null
///
/// The tower that has been destroyed
protected virtual void OnTargetTowerDestroyed(DamageableBehaviour tower)
{
if (m_TargetTower == tower)
{
m_TargetTower.removed -= OnTargetTowerDestroyed;
m_TargetTower = null;
}
}
///
/// Peforms the relevant path update for the states ,
/// and
///
protected override void PathUpdate()
{
switch (state)
{
case State.OnCompletePath:
OnCompletePathUpdate();
break;
case State.OnPartialPath:
OnPartialPathUpdate();
break;
case State.Attacking:
AttackingUpdate();
break;
}
}
///
/// Change to when path is no longer blocked or to
/// when the agent reaches
///
protected override void OnPartialPathUpdate()
{
if (!isPathBlocked)
{
state = State.OnCompletePath;
return;
}
// Check for closest tower at the end of the partial path
m_AttackAffector.towerTargetter.transform.position = m_NavMeshAgent.pathEndPosition;
Tower tower = GetClosestTower();
if (tower != m_TargetTower)
{
// if the current target is to be replaced, unsubscribe from removed event
if (m_TargetTower != null)
{
m_TargetTower.removed -= OnTargetTowerDestroyed;
}
// assign target, can be null
m_TargetTower = tower;
// if new target found subscribe to removed event
if (m_TargetTower != null)
{
m_TargetTower.removed += OnTargetTowerDestroyed;
}
}
if (m_TargetTower == null)
{
return;
}
float distanceToTower = Vector3.Distance(transform.position, m_TargetTower.transform.position);
if (!(distanceToTower < m_AttackAffector.towerTargetter.effectRadius))
{
return;
}
if (!m_AttackAffector.enabled)
{
m_AttackAffector.towerTargetter.transform.position = transform.position;
m_AttackAffector.enabled = true;
}
state = State.Attacking;
m_NavMeshAgent.isStopped = true;
}
///
/// The agent attacks until the path is available again or it has killed the target tower
///
protected void AttackingUpdate()
{
if (m_TargetTower != null)
{
return;
}
// River mod: 修改了Agent的移动方式,这个函数的模式已修改.
//MoveToNode();
// Resume path once blocking has been cleared
m_IsAttacking = false;
m_NavMeshAgent.isStopped = false;
m_AttackAffector.enabled = false;
state = isPathBlocked ? State.OnPartialPath : State.OnCompletePath;
// Move the Targetter back to the agent's position
m_AttackAffector.towerTargetter.transform.position = transform.position;
}
}
}