From b3597e5148e64a08abe5730396c4018ccfa76e22 Mon Sep 17 00:00:00 2001
From: chenxin <chenxin6991@163.com>
Date: Thu, 26 Nov 2020 16:26:11 +0800
Subject: [PATCH] buff预览界面打开时停止出怪

---
 Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs |  441 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 384 insertions(+), 57 deletions(-)

diff --git a/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs b/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs
index 633ef81..1c51b09 100644
--- a/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs
+++ b/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs
@@ -3,12 +3,13 @@
 using ActionGameFramework.Audio;
 using ActionGameFramework.Health;
 using Core.Health;
-using TowerDefense.Agents;
 using TowerDefense.Targetting;
 using TowerDefense.Towers;
 using TowerDefense.Towers.Projectiles;
 using UnityEngine;
 using KTGMGemClient;
+using TowerDefense.Agents;
+using TowerDefense.Level;
 
 namespace TowerDefense.Affectors
 {
@@ -26,6 +27,10 @@
         /// </summary>
         public GameObject projectile;
 
+        /// <summary>
+        /// 木塔最后一击是特殊攻击,需要替换projectile
+        /// </summary>
+        public GameObject woodProjectile_SP;
         // 
         protected GameObject projectile1;
         protected GameObject projectile2;
@@ -50,12 +55,16 @@
         /// </summary>
         public int maxAttackNum = 1;
 
-
         /// <summary>
         /// The fire rate in fires-per-second
         /// </summary>
-        public float fireRate;
+        [SerializeField]
+        private float projectileFireRate = 1;
 
+        public float FireRate
+        {
+            get { return 1 / GetFireDuration(); }
+        }
 
         /// <summary>
         /// 是否木属性数据
@@ -97,10 +106,14 @@
         /// </summary>
         protected float m_FireTimer;
 
+        protected float freezeBreathTimer;
+
         /// <summary>
         /// Reference to the current tracked enemy
         /// </summary>
         protected Targetable m_TrackingEnemy;
+
+        public TowerLevel towerLevel;
 
         /// <summary>
         /// 处理装弹时间.
@@ -108,11 +121,74 @@
         protected float fillBulletTime = 0.0f;
 
         /// <summary>
-        /// 充能时间
+        /// 火精灵充能时间
         /// </summary>
         protected float energyCalTime = 0;
+
         protected float fInEnergy = 0;
+
         protected float fBackupTimer = 0.0f;
+
+        /// <summary>
+        /// 水精灵的充能时间
+        /// </summary>
+        protected float freezeBreathCallTime = 0;
+
+        protected float inFreezeBreath;
+
+        protected float freezeBreathBackTimer = 0;
+
+        private int towerAttributeId;
+
+        /// <summary>
+        /// 火精灵技能固定攻击倍速
+        /// </summary>
+        /// <value></value>
+        protected float fireSpeed { get; set; } = 5f;
+
+        /// <summary>
+        /// 木属性精灵蓄力时间
+        /// </summary>
+        protected float woodChargeTime { get; set; } = 1.5f;
+
+        protected float woodRemainChargeTime { get; set; }
+
+        /// <summary>
+        /// 蓄力特效时间
+        /// </summary>
+        protected float woodChargeEffectTime { get; set; }
+
+        /// <summary>
+        /// 木属性精灵蓄力特效
+        /// </summary>
+        public GameObject WoodChargeEffect;
+
+        private GameObject woodChargeEffect;
+
+        public Transform WoodChargeTransform;
+
+        /// <summary>
+        /// 木属性正在瞄准的Agent
+        /// </summary>
+        protected Agent woodAimAgent;
+
+        /// <summary>
+        /// 火精灵攻击最终攻击倍速,里面计算了buff增加的倍速
+        /// </summary>
+        /// <value></value>
+        public float finalFireSpeed
+        {
+            get
+            {
+                FireRateAdd fireRateAdd = (FireRateAdd)EndlessBuffManager.instance.GetBuffInstanceByType(EndlessBuffEffectType.FireRateAdd);
+                float rateAdd = 0;
+
+                if (fireRateAdd != null)
+                    rateAdd = fireRateAdd.GetFireSpeedAdd(towerPtr.attributeId);
+                return rateAdd > 1 ? rateAdd : fireSpeed;
+            }
+        }
+
         /// <summary>
         /// Gets the search rate from the targetter
         /// </summary>
@@ -245,15 +321,38 @@
         /// </summary>
         protected virtual void SetUpTimers()
         {
-            m_FireTimer = 1 / fireRate;
             m_Launcher = GetComponent<ILauncher>();
         }
 
         TowerLevel myTower;
-
+        bool fireState = false;
         protected void updateTowerSkillData()
         {
-            // 
+            HandleBullet();
+            HandleEnergy();
+            HandleFreezeBreath();
+        }
+
+        // 处理木精灵装填子弹
+        private void HandleBullet()
+        {
+            if (woodRemainChargeTime > 0f)
+                woodRemainChargeTime -= Time.deltaTime;
+
+            if (woodChargeEffectTime > 0f)
+            {
+                woodChargeEffectTime -= Time.deltaTime;
+                UpdateWoodAim();
+
+                if (woodChargeEffectTime <= 0 && woodChargeEffect != null)
+                {
+                    towerPtr.IsWoodCharge = false;
+                    CancelWoodAim();
+                    Destroy(woodChargeEffect);
+                    woodChargeEffect = null;
+                }
+            }
+
             // 预留出来装填子弹的时间.
             if (fillBulletTime > 0)
             {
@@ -261,7 +360,7 @@
                 if (fillBulletTime <= 0.3f)
                 {
                     if (towerPtr && towerPtr.bulletCtl)
-                        towerPtr.bulletCtl.resetToMaxBullet();
+                        towerPtr.bulletCtl.ResetToMaxBullet();
                 }
 
                 if (fillBulletTime <= 0)
@@ -269,25 +368,119 @@
                     fillBulletTime = 0;
                 }
             }
+        }
 
-            // 
+        /// <summary>
+        /// 更新木属性瞄准
+        /// </summary>
+        private void UpdateWoodAim()
+        {
+            // 离得最近的 Agent
+            Agent agent = GetMinDistanceAgent();
+
+            if (agent != null)
+            {
+                // 还没有瞄准目标,直接分配
+                if (woodAimAgent == null)
+                {
+                    woodAimAgent = agent;
+                    towerPtr.WoodAimAgent = agent;
+
+                    if (agent.WoodAimCount == 0)
+                        agent.PlayWoodAimEffect();
+
+                    ++agent.WoodAimCount;
+                }
+                // 有小怪走到之前瞄准目标的前面 或者 之前瞄准的目标死亡,切换瞄准目标
+                else if (woodAimAgent.Id != agent.Id)
+                {
+                    if (woodAimAgent.WoodAimCount > 0)
+                    {
+                        --woodAimAgent.WoodAimCount;
+
+                        if (woodAimAgent.WoodAimCount == 0)
+                            woodAimAgent.StopWoodAimEffect();
+                    }
+
+                    woodAimAgent = agent;
+                    towerPtr.WoodAimAgent = agent;
+
+                    if (agent.WoodAimCount == 0)
+                        agent.PlayWoodAimEffect();
+
+                    ++agent.WoodAimCount;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 获取距离终点最近的Agent
+        /// </summary>
+        /// <returns></returns>
+        private Agent GetMinDistanceAgent()
+        {
+            Agent ret = null;
+            float minDistance = -1f;
+
+            WaveLineAgentInsMgr[] waveLineAgentIns = AgentInsManager.instance.GetWaveLineList();
+            WaveLineAgentInsMgr waveLineAgentInsMgr = waveLineAgentIns[waveLineID];
+            List<Agent> agents = waveLineAgentInsMgr.listAgent;
+            Vector3 endPos = EndlessLevelManager.instance.GetHomeBasePosition(waveLineID + 1);
+
+            for (int i = 0; i < agents.Count; ++i)
+            {
+                float distance = Mathf.Abs(agents[i].transform.position.z - endPos.z);
+
+                if (minDistance < 0 || distance < minDistance)
+                {
+                    minDistance = distance;
+                    ret = agents[i];
+                }
+            }
+
+            return ret;
+        }
+
+        /// <summary>
+        /// 取消木属性瞄准
+        /// </summary>
+        private void CancelWoodAim()
+        {
+            if (woodAimAgent != null)
+            {
+                if (woodAimAgent.WoodAimCount > 0)
+                {
+                    --woodAimAgent.WoodAimCount;
+
+                    if (woodAimAgent.WoodAimCount == 0)
+                        woodAimAgent.StopWoodAimEffect();
+                }
+            }
+
+            woodAimAgent = null;
+        }
+
+        // 处理火精灵充能
+        private void HandleEnergy()
+        {
             // 充能时间的处理
             if (towerPtr && towerPtr.energyCtl)
             {
-                if (this.fInEnergy <= 0)
+                if (fInEnergy <= 0)
                 {
-                    this.energyCalTime += Time.deltaTime;
+                    energyCalTime += Time.deltaTime;
                     float process = energyCalTime % 11.0f;
                     int proint = (int)Math.Floor(process);
                     proint += towerPtr.uiProOffset;
                     towerPtr.energyCtl.SetEnergyProcessFloat(process);
                     if (proint == 10)
                     {
-                        fInEnergy = 5.0f;
+                        fireState = true;
+                        fInEnergy = finalFireSpeed;
                         myTower.SetFireMatSpeed(true);//设置了火宝石快速攻击
                         // 设置多倍攻击速度
                         fBackupTimer = m_FireTimer;
-                        m_FireTimer = m_FireTimer / 3.0f;
+                        m_FireTimer = m_FireTimer / finalFireSpeed;
 
                         towerPtr.uiProOffset = 0;
                         towerPtr.PlayEnergyEffect(true);
@@ -300,9 +493,10 @@
                     {
                         myTower.SetFireMatSpeed(false);//恢复了火宝石攻击速度
 
+                        fireState = false;
                         EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.FireTowerChargeEnd);
                         fInEnergy = 0.0f;
-                        this.energyCalTime = 0.0f;
+                        energyCalTime = 0.0f;
                         towerPtr.energyCtl.SetEnergyProgress(0);
 
                         // 恢复正常攻击速度 
@@ -312,8 +506,116 @@
 
                     }
                 }
-
             }
+        }
+
+        // 处理水精灵的充能
+        private void HandleFreezeBreath()
+        {
+            if (towerPtr && towerPtr.FreezeBreathCtrl)
+            {
+                Damager damager = projectile.gameObject.GetComponent<Damager>();
+                float finalDamage = damager.damage;
+
+                List<EndlessBuffConfig> list = EndlessBuffManager.instance.GetBuffListByEffectType(EndlessBuffEffectType.AttackAdd, towerPtr.attributeId);
+                float ratio = 0;
+                float add = 0;
+
+                if (list.Count > 0)
+                {
+                    for (int i = 0; i < list.Count; ++i)
+                    {
+                        ratio += list[i].Config.buff_effect[1];
+                        add += list[i].Config.buff_effect[2];
+                    }
+                }
+
+                finalDamage += (ratio / 100f) * finalDamage + add;
+
+                if (inFreezeBreath <= 0)
+                {
+                    freezeBreathCallTime += Time.deltaTime;
+                    float process = freezeBreathCallTime % (FreezeBreath.ChargeTime + 1);
+                    int processInt = (int)Mathf.Floor(process);
+                    processInt += towerPtr.FreezeBreathProgressOffset;
+                    towerPtr.FreezeBreathCtrl.SetProgress(process);
+
+                    if (processInt == (int)Mathf.Floor(FreezeBreath.ChargeTime))
+                    {
+                        inFreezeBreath = towerPtr.FreezeBreathCtrl.SkillTime;
+                        towerPtr.FreezeBreathProgressOffset = 0;
+                        towerPtr.PlayFreezeBreathEffect(true);
+                        towerPtr.FreezeBreathCtrl.ReleaseCount = 1;
+                        towerPtr.FreezeBreathCtrl.PlayFreezeEffect(waveLineID);
+                        towerPtr.FreezeBreathCtrl.ReleaseFreeze(waveLineID, finalDamage, damager.alignmentProvider);
+                    }
+                }
+                else
+                {
+                    inFreezeBreath -= Time.deltaTime;
+                    int time = Mathf.FloorToInt(towerPtr.FreezeBreathCtrl.EffectTime / (towerPtr.FreezeBreathCtrl.DamageCount - 1) * 10);
+                    int interval = Mathf.FloorToInt(inFreezeBreath * 10);
+                    int offset = Mathf.FloorToInt(towerPtr.FreezeBreathCtrl.SkillTime * 10) - Mathf.FloorToInt(towerPtr.FreezeBreathCtrl.EffectTime * 10);
+
+                    if (interval == time * (towerPtr.FreezeBreathCtrl.DamageCount - towerPtr.FreezeBreathCtrl.ReleaseCount - 1) + offset && towerPtr.FreezeBreathCtrl.ReleaseCount < towerPtr.FreezeBreathCtrl.DamageCount)
+                    {
+                        ++towerPtr.FreezeBreathCtrl.ReleaseCount;
+                        towerPtr.FreezeBreathCtrl.ReleaseFreeze(waveLineID, finalDamage, damager.alignmentProvider);
+                    }
+
+                    if (inFreezeBreath <= 0)
+                    {
+                        inFreezeBreath = 0;
+                        freezeBreathCallTime = 0;
+                        towerPtr.FreezeBreathCtrl.SetProgress(0);
+                        towerPtr.PlayFreezeBreathEffect(false);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// This function is called when the object becomes enabled and active.
+        /// </summary>
+        void OnEnable()
+        {
+            if (towerPtr && towerPtr.energyCtl)
+            {
+                if (fireState)
+                {
+                    myTower.SetFireMatSpeed(true);//设置了火宝石快速攻击
+
+                    towerPtr.PlayEnergyEffect(true);
+                }
+            }
+
+            // 如果在木属性蓄力期间,让瞄准动画播放
+            if (towerPtr && towerPtr.IsWoodCharge && woodAimAgent != null)
+                woodAimAgent.PlayWoodAimEffect();
+        }
+
+        /// <summary>
+        /// This function is called when the behaviour becomes disabled or inactive.
+        /// </summary>
+        void OnDisable()
+        {
+            if (towerPtr && towerPtr.energyCtl)
+            {
+                towerPtr.PlayEnergyEffect(false, false);
+            }
+
+            if (towerPtr && towerPtr.FreezeBreathCtrl)
+                towerPtr.PlayFreezeBreathEffect(false, false);
+        }
+
+        /// <summary>
+        /// 获取子弹发射时间间隔
+        /// </summary>
+        public float GetFireDuration()
+        {
+            DecreaseTowerAttackCD endlessBuff = (DecreaseTowerAttackCD)EndlessBuffManager.instance.GetBuffInstanceByType(EndlessBuffEffectType.DecreaseTowerAttackCD);
+
+            return endlessBuff != null ? endlessBuff.GetDecreaseCD(towerPtr.attributeId, 1 / projectileFireRate) : 1 / projectileFireRate;
         }
 
         /// <summary>
@@ -321,75 +623,100 @@
         /// </summary>
         protected virtual void Update()
         {
-            if (m_Launcher == null) return;
+            if (m_Launcher == null || towerPtr != null && !towerPtr.CanAttack) return;
 
             // 处理当前Affector所在Tower对应的技能
             updateTowerSkillData();
 
             m_FireTimer -= Time.deltaTime;
-            if (trackingEnemy == null)
-                m_TrackingEnemy = targetter.GetTarget(waveLineID, bWoodAffector);
-            if (trackingEnemy != null && m_FireTimer <= 0.0f)
-            {
-                OnFireTimer();
-                m_FireTimer = 1 / fireRate;
-                // 多倍攻速:
-                if (fInEnergy > 0.0f)
-                    m_FireTimer = m_FireTimer / 5.0f;
-            }
-        }
+            m_TrackingEnemy = targetter.GetTarget(waveLineID, bWoodAffector);
 
-        /// <summary>
-        /// Fired at every poll of the fire rate timer
-        /// </summary>
-        protected virtual void OnFireTimer()
-        {
-            if (fireCondition != null)
+            if (m_TrackingEnemy != null && m_FireTimer < 0)
             {
-                if (!fireCondition())
+                m_FireTimer = GetFireDuration();
+
+                if (fInEnergy > 0)
+                    m_FireTimer /= finalFireSpeed;
+
+                towerLevel.FireSpeed = fInEnergy > 0 ? finalFireSpeed : 1f;
+
+                if (towerPtr && towerPtr.bulletCtl != null)
                 {
-                    return;
+                    int bnum = towerPtr.bulletCtl.GetCtlProgress();
+
+                    // 蓄力时间内不攻击
+                    if (bnum == 0 || woodRemainChargeTime > 0f) return;
                 }
+
+                if (towerPtr && towerPtr.FreezeBreathCtrl != null)
+                {
+                    // 冷冻气息期间不攻击
+                    if (inFreezeBreath > 0.0001f) return;
+                }
+
+                towerLevel.ChangeState(TowerActionState.Attack);
             }
-            FireProjectile();
         }
 
         /// <summary>
         /// Common logic when attacking
         /// 调用攻击的核心函数,由这个函数发起真正的攻击,多目标或者单目标
         /// </summary>
-        protected virtual void FireProjectile()
+        public virtual void FireProjectile()
         {
             // 不再处理多子弹攻击,确保只有一个弹道
             isMultiAttack = false;
             m_TrackingEnemy = targetter.GetTarget(waveLineID, bWoodAffector);
-            if ((m_TrackingEnemy == null) || (fillBulletTime > 0))
-            {
-                if (this.towerPtr)
-                    towerPtr.setTowerState(false);
-                return;
-            }
-            else
-            {
-                if (this.towerPtr)
-                    towerPtr.setTowerState(true);
-            }
 
-            // 
+            GameObject go = damagerProjectile.gameObject;
+
+            if (m_TrackingEnemy == null || fillBulletTime > 0) return;
+
+            go.GetComponent<Damager>().IsEnhancedBullet = false;
+
             // 处理子弹充能相关的内容
-            if (towerPtr && (towerPtr.bulletCtl != null))
+            if (towerPtr && towerPtr.bulletCtl != null)
             {
                 int bnum = towerPtr.bulletCtl.decBullet();
-                // 
-                if (bnum == 0)
+                // 暴击子弹的数量,如果获得相应buff可能会修改暴击子弹数量
+                int critBulletNum = towerPtr.bulletCtl.CritBulletNum;
+
+                if (bnum < critBulletNum)
                 {
-                    damagerProjectile.damageMulti = 5.0f;
-                    fillBulletTime = 2.0f;
+                    if (bnum == 0)
+                        // 不需要装填时间
+                        fillBulletTime = 0.1f;
+
+                    //这里需要替换特效
+                    var poolable = Core.Utilities.Poolable.TryGetPoolable<Core.Utilities.Poolable>(woodProjectile_SP);
+                    go = poolable.gameObject;
+                    Damager tmpDamager = go.GetComponent<Damager>();
+                    tmpDamager.damageMulti = 10.0f;
+                    tmpDamager.damage = damagerProjectile.damage;
+                    tmpDamager.IsEnhancedBullet = true;
+                }
+
+                // 下一颗子弹是强化子弹,然后直接蓄力
+                if (bnum - 1 >= 0 && bnum - 1 < critBulletNum)
+                {
+                    woodRemainChargeTime = woodChargeTime;
+                    towerPtr.IsWoodCharge = true;
+                    DecreaseWoodChargeTime decreaseWoodChargeTime = (DecreaseWoodChargeTime)EndlessBuffManager.instance.GetBuffInstanceByType(EndlessBuffEffectType.DecreaseWoodChargeTime);
+
+                    if (decreaseWoodChargeTime != null)
+                        woodRemainChargeTime = decreaseWoodChargeTime.GetWoodChargeTime(woodChargeTime);
+
+                    woodChargeEffectTime = woodRemainChargeTime + 0.5f / towerLevel.ActionAnimator.speed;
+                    woodChargeEffect = Instantiate(WoodChargeEffect);
+                    woodChargeEffect.transform.SetParent(gameObject.transform);
+                    woodChargeEffect.transform.SetPositionAndRotation(WoodChargeTransform.position, WoodChargeTransform.rotation);
+                    ParticleSystem ps = woodChargeEffect.transform.GetChild(0).GetComponent<ParticleSystem>();
+                    ps.Play();
                 }
             }
             else
             {
-                if (this.towerPtr)
+                if (towerPtr)
                     towerPtr.setTowerState(true);
             }
 
@@ -397,13 +724,13 @@
             {
                 List<Targetable> enemies = towerTargetter.GetAllTargets();
                 if ((enemies != null) && (Targetter.bSearchTarget))
-                    m_Launcher.Launch(enemies, projectile, projectilePoints, this.maxAttackNum);
+                    m_Launcher.Launch(enemies, projectile, projectilePoints, maxAttackNum);
             }
             else
             {
                 if (Targetter.bSearchTarget)
                 {
-                    m_Launcher.Launch(m_TrackingEnemy, damagerProjectile.gameObject, projectilePoints);
+                    m_Launcher.Launch(m_TrackingEnemy, go, projectilePoints);
                     if (AudioSourceManager.Ins)
                         AudioSourceManager.Ins.Play(audioEnum);
                 }

--
Gitblit v1.9.1