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; } } }