liuzhiwei
2020-12-08 3a33d54f705e79cb049ec2bd5711c37e6f73ad08
Assets/Scripts/TowerDefense/Agents/AttackingAgent.cs
@@ -1,182 +1,41 @@
using Core.Health;
using TowerDefense.Affectors;
using TowerDefense.Towers;
using UnityEngine;
namespace TowerDefense.Agents
namespace TowerDefense.Agents
{
   /// <summary>
   /// An implementation of Agent that will attack
   /// any Towers that block its path
   /// </summary>
   public class AttackingAgent : Agent
   {
      /// <summary>
      /// Tower to target
      /// </summary>
      protected Tower m_TargetTower;
    /// <summary>
    /// An implementation of Agent that will attack
    /// any Towers that block its path
    /// </summary>
    public class AttackingAgent : Agent
    {
        public override void Initialize()
        {
            base.Initialize();
        }
      /// <summary>
      /// The attached attack affector
      /// </summary>
      protected AttackAffector m_AttackAffector;
      /// <summary>
      /// Is this agent currently engaging a tower?
      /// </summary>
      protected bool m_IsAttacking;
        /// <summary>
        /// Unsubscribes from tracked towers removed event
        /// and disables the attached attack affector
        /// </summary>
        public override void Remove()
        {
            base.Remove();
        }
      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;
      }
        /// <summary>
        /// Peforms the relevant path update for the states <see cref="Agent.State.OnCompletePath"/>,
        /// <see cref="Agent.State.OnPartialPath"/> and <see cref="Agent.State.Attacking"/>
        /// </summary>
        protected override void PathUpdate()
        {
      /// <summary>
      /// Unsubscribes from tracked towers removed event
      /// and disables the attached attack affector
      /// </summary>
      public override void Remove()
      {
         base.Remove();
         if (m_TargetTower != null)
         {
            m_TargetTower.removed -= OnTargetTowerDestroyed;
         }
         m_AttackAffector.enabled = false;
         m_TargetTower = null;
      }
        }
      /// <summary>
      /// Gets the closest tower to the agent
      /// </summary>
      /// <returns>The closest tower</returns>
      protected Tower GetClosestTower()
      {
         var towerController = m_AttackAffector.towerTargetter.GetTarget( -1 ) as Tower;
         return towerController;
      }
        /// <summary>
        /// Change to <see cref="Agent.State.OnCompletePath" /> when path is no longer blocked or to
        /// <see cref="Agent.State.Attacking" /> when the agent reaches <see cref="AttackingAgent.m_TargetTower" />
        /// </summary>
        protected override void OnPartialPathUpdate()
        {
      /// <summary>
      /// Caches the Attack Affector if necessary
      /// </summary>
      protected override void LazyLoad()
      {
         base.LazyLoad();
         if (m_AttackAffector == null)
         {
            m_AttackAffector = GetComponent<AttackAffector>();
         }
      }
      /// <summary>
      /// If the tower is destroyed while other agents attack it, ensure it becomes null
      /// </summary>
      /// <param name="tower">The tower that has been destroyed</param>
      protected virtual void OnTargetTowerDestroyed(DamageableBehaviour tower)
      {
         if (m_TargetTower == tower)
         {
            m_TargetTower.removed -= OnTargetTowerDestroyed;
            m_TargetTower = null;
         }
      }
      /// <summary>
      /// Peforms the relevant path update for the states <see cref="Agent.State.OnCompletePath"/>,
      /// <see cref="Agent.State.OnPartialPath"/> and <see cref="Agent.State.Attacking"/>
      /// </summary>
      protected override void PathUpdate()
      {
         switch (state)
         {
            case State.OnCompletePath:
               OnCompletePathUpdate();
               break;
            case State.OnPartialPath:
               OnPartialPathUpdate();
               break;
            case State.Attacking:
               AttackingUpdate();
               break;
         }
      }
      /// <summary>
      /// Change to <see cref="Agent.State.OnCompletePath" /> when path is no longer blocked or to
      /// <see cref="Agent.State.Attacking" /> when the agent reaches <see cref="AttackingAgent.m_TargetTower" />
      /// </summary>
      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;
      }
      /// <summary>
      /// The agent attacks until the path is available again or it has killed the target tower
      /// </summary>
      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;
      }
   }
        }
    }
}