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 | 971 +++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 713 insertions(+), 258 deletions(-) diff --git a/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs b/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs index 43013f7..1c51b09 100644 --- a/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs +++ b/Assets/Scripts/TowerDefense/Affectors/AttackAffector.cs @@ -3,315 +3,770 @@ 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 { - /// <summary> - /// The common effect for handling firing projectiles to attack - /// - /// Requires an ILauncher but it is not automatically added - /// Add an ILauncher implementation to this GameObject before you add this script - /// </summary> - [RequireComponent(typeof(ILauncher))] - public class AttackAffector : Affector, ITowerRadiusProvider - { - /// <summary> - /// The projectile used to attack - /// </summary> - public GameObject projectile; + /// <summary> + /// The common effect for handling firing projectiles to attack + /// + /// Requires an ILauncher but it is not automatically added + /// Add an ILauncher implementation to this GameObject before you add this script + /// </summary> + [RequireComponent(typeof(ILauncher))] + public class AttackAffector : Affector, ITowerRadiusProvider + { + /// <summary> + /// The projectile used to attack + /// </summary> + public GameObject projectile; - // - protected GameObject projectile1; - protected GameObject projectile2; + /// <summary> + /// 木塔最后一击是特殊攻击,需要替换projectile + /// </summary> + public GameObject woodProjectile_SP; + // + protected GameObject projectile1; + protected GameObject projectile2; - /// <summary> - /// The list of points to launch the projectiles from - /// </summary> - public Transform[] projectilePoints; + /// <summary> + /// The list of points to launch the projectiles from + /// </summary> + public Transform[] projectilePoints; - /// <summary> - /// The reference to the center point where the tower will search from - /// </summary> - public Transform epicenter; + /// <summary> + /// The reference to the center point where the tower will search from + /// </summary> + public Transform epicenter; - /// <summary> - /// Configuration for when the tower does splash damage - /// </summary> - public bool isMultiAttack; + /// <summary> + /// Configuration for when the tower does splash damage + /// </summary> + public bool isMultiAttack; - /// <summary> - /// 如果是多目标攻击,最多攻击目标 - /// </summary> - public int maxAttackNum = 1; - + /// <summary> + /// 如果是多目标攻击,最多攻击目标 + /// </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> - /// 是否木属性数据 - /// </summary> - public bool bWoodAffector = false; + /// <summary> + /// 是否木属性数据 + /// </summary> + public bool bWoodAffector = false; - /// <summary> - /// The audio source to play when firing - /// </summary> - public RandomAudioSource randomAudioSource; + /// <summary> + /// The audio source to play when firing + /// </summary> + public RandomAudioSource randomAudioSource; - /// <summary> - /// Gets the targetter - /// </summary> - public Targetter towerTargetter; + /// <summary> + /// Gets the targetter + /// </summary> + public Targetter towerTargetter; - /// <summary> - /// Color of effect radius visualization - /// </summary> - public Color radiusEffectColor; + /// <summary> + /// Color of effect radius visualization + /// </summary> + public Color radiusEffectColor; - /// <summary> - /// Search condition - /// </summary> - public Filter searchCondition; + /// <summary> + /// Search condition + /// </summary> + public Filter searchCondition; - /// <summary> - /// Fire condition - /// </summary> - public Filter fireCondition; + /// <summary> + /// Fire condition + /// </summary> + public Filter fireCondition; - /// <summary> - /// The reference to the attached launcher - /// </summary> - protected ILauncher m_Launcher; + /// <summary> + /// The reference to the attached launcher + /// </summary> + protected ILauncher m_Launcher; - /// <summary> - /// The time before firing is possible - /// </summary> - protected float m_FireTimer; + /// <summary> + /// The time before firing is possible + /// </summary> + protected float m_FireTimer; - /// <summary> - /// Reference to the current tracked enemy - /// </summary> - protected Targetable m_TrackingEnemy; + protected float freezeBreathTimer; - /// <summary> - /// Gets the search rate from the targetter - /// </summary> - public float searchRate - { - get { return towerTargetter.searchRate; } - set { towerTargetter.searchRate = value; } - } + /// <summary> + /// Reference to the current tracked enemy + /// </summary> + protected Targetable m_TrackingEnemy; - /// <summary> - /// Gets the targetable - /// </summary> - public Targetable trackingEnemy - { - get { return m_TrackingEnemy; } - } + public TowerLevel towerLevel; - /// <summary> - /// Gets or sets the attack radius - /// </summary> - public float effectRadius - { - get { return towerTargetter.effectRadius; } - } + /// <summary> + /// 处理装弹时间. + /// </summary> + protected float fillBulletTime = 0.0f; - public Color effectColor - { - get { return radiusEffectColor; } - } + /// <summary> + /// 火精灵充能时间 + /// </summary> + protected float energyCalTime = 0; - public Targetter targetter - { - get { return towerTargetter; } - } + protected float fInEnergy = 0; - /// <summary> - /// Initializes the attack affector - /// </summary> - public override void Initialize(IAlignmentProvider affectorAlignment) - { - Initialize(affectorAlignment, -1); - } + protected float fBackupTimer = 0.0f; - /// <summary> - /// 返回可能存在的Targetter. - /// </summary> - /// <returns></returns> - public override TowerDefense.Targetting.Targetter GetTargetter() - { - return targetter; - } + /// <summary> + /// 水精灵的充能时间 + /// </summary> + protected float freezeBreathCallTime = 0; - /// <summary> - /// Initialises the attack affector with a layer mask - /// </summary> - public override void Initialize(IAlignmentProvider affectorAlignment, LayerMask mask) - { - base.Initialize(affectorAlignment, mask); - SetUpTimers(); + protected float inFreezeBreath; - towerTargetter.ResetTargetter(); - towerTargetter.alignment = affectorAlignment; - towerTargetter.acquiredTarget += OnAcquiredTarget; - towerTargetter.lostTarget += OnLostTarget; - } + protected float freezeBreathBackTimer = 0; - void OnDestroy() - { - towerTargetter.acquiredTarget -= OnAcquiredTarget; - towerTargetter.lostTarget -= OnLostTarget; - } + private int towerAttributeId; - void OnLostTarget() - { - m_TrackingEnemy = null; - } + /// <summary> + /// 火精灵技能固定攻击倍速 + /// </summary> + /// <value></value> + protected float fireSpeed { get; set; } = 5f; - void OnAcquiredTarget(Targetable acquiredTarget) - { - m_TrackingEnemy = acquiredTarget; - } + /// <summary> + /// 木属性精灵蓄力时间 + /// </summary> + protected float woodChargeTime { get; set; } = 1.5f; - public Damager damagerProjectile - { - get { return projectile == null ? null : projectile.GetComponent<Damager>(); } - } + protected float woodRemainChargeTime { get; set; } - public Damager damagerProjectile1 - { - get { return projectile == null ? null : projectile.GetComponent<Damager>(); } - } + /// <summary> + /// 蓄力特效时间 + /// </summary> + protected float woodChargeEffectTime { get; set; } - public Damager damagerProjectile2 - { - get { return projectile == null ? null : projectile.GetComponent<Damager>(); } - } + /// <summary> + /// 木属性精灵蓄力特效 + /// </summary> + public GameObject WoodChargeEffect; + private GameObject woodChargeEffect; - /// <summary> - /// Returns the total projectile damage - /// </summary> - public float GetProjectileDamage() - { - var splash = projectile.GetComponent<SplashDamager>(); - float splashDamage = splash != null ? splash.damage : 0; - return damagerProjectile.finalDamage + splashDamage; - } + public Transform WoodChargeTransform; - /// <summary> - /// Initialise the RepeatingTimer - /// </summary> - protected virtual void SetUpTimers() - { - m_FireTimer = 1 / fireRate; - m_Launcher = GetComponent<ILauncher>(); - } + /// <summary> + /// 木属性正在瞄准的Agent + /// </summary> + protected Agent woodAimAgent; - /// <summary> - /// Update the timers - /// </summary> - protected virtual void Update() - { - 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; - } - } - - /// <summary> - /// Fired at every poll of the fire rate timer - /// </summary> - protected virtual void OnFireTimer() - { - if (fireCondition != null) - { - if (!fireCondition()) - { - return; - } - } - FireProjectile(); - } - - /// <summary> - /// Common logic when attacking - /// 调用攻击的核心函数,由这个函数发起真正的攻击,多目标或者单目标 - /// </summary> - protected virtual void FireProjectile() - { - // WORK START: 确保获取 - // 不再处理多子弹攻击,确保只有一个弹道 - isMultiAttack = false; - m_TrackingEnemy = targetter.GetTarget( waveLineID, bWoodAffector ); - if (m_TrackingEnemy == null) - { - if (this.towerPtr) - towerPtr.setTowerState(false); - return; - }else + /// <summary> + /// 火精灵攻击最终攻击倍速,里面计算了buff增加的倍速 + /// </summary> + /// <value></value> + public float finalFireSpeed + { + get { - if (this.towerPtr) - towerPtr.setTowerState(true); + 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> + public float searchRate + { + get { return towerTargetter.searchRate; } + set { towerTargetter.searchRate = value; } + } + + /// <summary> + /// Gets the targetable + /// </summary> + public Targetable trackingEnemy + { + get { return m_TrackingEnemy; } + } + + /// <summary> + /// Gets or sets the attack radius + /// </summary> + public float effectRadius + { + get { return towerTargetter.effectRadius; } + } + + public Color effectColor + { + get { return radiusEffectColor; } + } + + public Targetter targetter + { + get { return towerTargetter; } + } + + /// <summary> + /// Initializes the attack affector + /// </summary> + public override void Initialize(IAlignmentProvider affectorAlignment) + { + Initialize(affectorAlignment, -1); + } + + /// <summary> + /// 返回可能存在的Targetter. + /// </summary> + /// <returns></returns> + public override TowerDefense.Targetting.Targetter GetTargetter() + { + return targetter; + } + + /// <summary> + /// Initialises the attack affector with a layer mask + /// </summary> + public override void Initialize(IAlignmentProvider affectorAlignment, LayerMask mask) + { + base.Initialize(affectorAlignment, mask); + SetUpTimers(); + + towerTargetter.ResetTargetter(); + towerTargetter.alignment = affectorAlignment; + towerTargetter.acquiredTarget += OnAcquiredTarget; + // towerTargetter.lostTarget += OnLostTarget; + GetAudioEnum(); + + myTower = transform.parent.GetComponent<TowerLevel>(); + + } + private AudioEnum audioEnum;//当前音乐的种类 + + void GetAudioEnum() + { + if (transform.parent.name.StartsWith("GrowUpTower")) + { + //火元素 + audioEnum = AudioEnum.FireTAttack; + } + else if (transform.parent.name.StartsWith("BlinkTower")) + { + //木元素 + audioEnum = AudioEnum.WoodTAttack; + } + else if (transform.parent.name.StartsWith("CopyCatTower")) + { + //水元素 + audioEnum = AudioEnum.WaterTAttack; + } + } + + void OnDestroy() + { + towerTargetter.acquiredTarget -= OnAcquiredTarget; + // towerTargetter.lostTarget -= OnLostTarget; + } + + void OnAcquiredTarget(Targetable acquiredTarget) + { + // m_TrackingEnemy = acquiredTarget; + } + + public Damager damagerProjectile + { + get { return projectile == null ? null : projectile.GetComponent<Damager>(); } + } + + public Damager damagerProjectile1 + { + get { return projectile == null ? null : projectile.GetComponent<Damager>(); } + } + + public Damager damagerProjectile2 + { + get { return projectile == null ? null : projectile.GetComponent<Damager>(); } + } + + + /// <summary> + /// Returns the total projectile damage + /// </summary> + public float GetProjectileDamage() + { + var splash = projectile.GetComponent<SplashDamager>(); + float splashDamage = splash != null ? splash.damage : 0; + return damagerProjectile.finalDamage + splashDamage; + } + + /// <summary> + /// Initialise the RepeatingTimer + /// </summary> + protected virtual void SetUpTimers() + { + 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 (isMultiAttack) - { - List<Targetable> enemies = towerTargetter.GetAllTargets(); - if( (enemies != null)&&(Targetter.bSearchTarget) ) - m_Launcher.Launch(enemies, projectile, projectilePoints,this.maxAttackNum); - } - else - { - if(Targetter.bSearchTarget ) - m_Launcher.Launch(m_TrackingEnemy, damagerProjectile.gameObject, projectilePoints); - } - if (randomAudioSource != null) - { - if( Targetter.bSearchTarget ) - randomAudioSource.PlayRandomClip(); - } - } + // 预留出来装填子弹的时间. + if (fillBulletTime > 0) + { + fillBulletTime -= Time.deltaTime; + if (fillBulletTime <= 0.3f) + { + if (towerPtr && towerPtr.bulletCtl) + towerPtr.bulletCtl.ResetToMaxBullet(); + } - /// <summary> - /// A delegate to compare distances of components - /// </summary> - /// <param name="first"></param> - /// <param name="second"></param> - protected virtual int ByDistance(Targetable first, Targetable second) - { - float firstSqrMagnitude = Vector3.SqrMagnitude(first.position - epicenter.position); - float secondSqrMagnitude = Vector3.SqrMagnitude(second.position - epicenter.position); - return firstSqrMagnitude.CompareTo(secondSqrMagnitude); - } + if (fillBulletTime <= 0) + { + 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 (fInEnergy <= 0) + { + energyCalTime += Time.deltaTime; + float process = energyCalTime % 11.0f; + int proint = (int)Math.Floor(process); + proint += towerPtr.uiProOffset; + towerPtr.energyCtl.SetEnergyProcessFloat(process); + if (proint == 10) + { + fireState = true; + fInEnergy = finalFireSpeed; + myTower.SetFireMatSpeed(true);//设置了火宝石快速攻击 + // 设置多倍攻击速度 + fBackupTimer = m_FireTimer; + m_FireTimer = m_FireTimer / finalFireSpeed; + + towerPtr.uiProOffset = 0; + towerPtr.PlayEnergyEffect(true); + } + } + else + { + fInEnergy -= Time.deltaTime; + if (fInEnergy <= 0) + { + myTower.SetFireMatSpeed(false);//恢复了火宝石攻击速度 + + fireState = false; + EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.FireTowerChargeEnd); + fInEnergy = 0.0f; + energyCalTime = 0.0f; + towerPtr.energyCtl.SetEnergyProgress(0); + + // 恢复正常攻击速度 + m_FireTimer = fBackupTimer; + + towerPtr.PlayEnergyEffect(false); + + } + } + } + } + + // 处理水精灵的充能 + 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> + /// Update the timers + /// </summary> + protected virtual void Update() + { + if (m_Launcher == null || towerPtr != null && !towerPtr.CanAttack) return; + + // 处理当前Affector所在Tower对应的技能 + updateTowerSkillData(); + + m_FireTimer -= Time.deltaTime; + m_TrackingEnemy = targetter.GetTarget(waveLineID, bWoodAffector); + + if (m_TrackingEnemy != null && m_FireTimer < 0) + { + m_FireTimer = GetFireDuration(); + + if (fInEnergy > 0) + m_FireTimer /= finalFireSpeed; + + towerLevel.FireSpeed = fInEnergy > 0 ? finalFireSpeed : 1f; + + if (towerPtr && towerPtr.bulletCtl != null) + { + 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); + } + } + + /// <summary> + /// Common logic when attacking + /// 调用攻击的核心函数,由这个函数发起真正的攻击,多目标或者单目标 + /// </summary> + public virtual void FireProjectile() + { + // 不再处理多子弹攻击,确保只有一个弹道 + isMultiAttack = false; + m_TrackingEnemy = targetter.GetTarget(waveLineID, bWoodAffector); + + GameObject go = damagerProjectile.gameObject; + + if (m_TrackingEnemy == null || fillBulletTime > 0) return; + + go.GetComponent<Damager>().IsEnhancedBullet = false; + + // 处理子弹充能相关的内容 + if (towerPtr && towerPtr.bulletCtl != null) + { + int bnum = towerPtr.bulletCtl.decBullet(); + // 暴击子弹的数量,如果获得相应buff可能会修改暴击子弹数量 + int critBulletNum = towerPtr.bulletCtl.CritBulletNum; + + if (bnum < critBulletNum) + { + 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 (towerPtr) + towerPtr.setTowerState(true); + } + + if (isMultiAttack) + { + List<Targetable> enemies = towerTargetter.GetAllTargets(); + if ((enemies != null) && (Targetter.bSearchTarget)) + m_Launcher.Launch(enemies, projectile, projectilePoints, maxAttackNum); + } + else + { + if (Targetter.bSearchTarget) + { + m_Launcher.Launch(m_TrackingEnemy, go, projectilePoints); + if (AudioSourceManager.Ins) + AudioSourceManager.Ins.Play(audioEnum); + } + } + if (randomAudioSource != null) + { + if (Targetter.bSearchTarget) + randomAudioSource.PlayRandomClip(); + } + } + + /// <summary> + /// A delegate to compare distances of components + /// </summary> + /// <param name="first"></param> + /// <param name="second"></param> + protected virtual int ByDistance(Targetable first, Targetable second) + { + float firstSqrMagnitude = Vector3.SqrMagnitude(first.position - epicenter.position); + float secondSqrMagnitude = Vector3.SqrMagnitude(second.position - epicenter.position); + return firstSqrMagnitude.CompareTo(secondSqrMagnitude); + } #if UNITY_EDITOR - /// <summary> - /// Draws the search area - /// </summary> - void OnDrawGizmosSelected() - { - Gizmos.DrawWireSphere(epicenter.position, towerTargetter.effectRadius); - } + /// <summary> + /// Draws the search area + /// </summary> + void OnDrawGizmosSelected() + { + Gizmos.DrawWireSphere(epicenter.position, towerTargetter.effectRadius); + } #endif - } + } - /// <summary> - /// A delegate for boolean calculation logic - /// </summary> - public delegate bool Filter(); + /// <summary> + /// A delegate for boolean calculation logic + /// </summary> + public delegate bool Filter(); } \ No newline at end of file -- Gitblit v1.9.1