Beispiel #1
0
		IEnumerator _UnitOverlay(Unit unit){
			if(overlayedUnitList.Contains(unit)) yield break;
			
			overlayedUnitList.Add(unit);
			
			UnitOverlay overlay=GetUnusedOverlay();
			overlay.rootObj.SetActive(true);
			
			if(unit.defaultShield>0) overlay.barShield.gameObject.SetActive(true);
			else overlay.barShield.gameObject.SetActive(false);
			
			while(unit!=null && !unit.dead && unit.thisObj.activeInHierarchy){
				overlay.barHP.value=unit.HP/unit.fullHP;
				if(unit.defaultShield>0) overlay.barShield.value=unit.shield/unit.fullShield;
				
				Vector3 screenPos = mainCam.WorldToScreenPoint(unit.thisT.position+new Vector3(0, 0, 0));
				overlay.rootT.localPosition=(screenPos+new Vector3(0, 20, 0))/UI.GetScaleFactor();
				
				if(overlay.barHP.value==1 && overlay.barShield.value==1) break;
				
				yield return null;
			}
			
			overlay.rootObj.SetActive(false);
			overlayedUnitList.Remove(unit);
		}
        public void Shoot(AttackInstance attInst=null, Transform sp=null)
        {
            if(attInst==null || attInst.tgtUnit==null){
                ObjectPoolManager.Unspawn(thisObj);
                return;
            }

            attInstance=attInst;
            target=attInstance.tgtUnit;
            targetPos=target.GetTargetT().position;
            hitThreshold=Mathf.Max(0.1f, target.hitThreshold);

            shootPoint=sp;
            if(shootPoint!=null) thisT.rotation=shootPoint.rotation;
            shootPointPos=shootPoint!=null ? shootPoint.position : thisT.position ;

            if(shootEffect!=null) ObjectPoolManager.Spawn(shootEffect, thisT.position, thisT.rotation);

            hit=false;

            if(type==_ShootObjectType.Projectile) StartCoroutine(ProjectileRoutine());
            if(type==_ShootObjectType.Beam) StartCoroutine(BeamRoutine());
            if(type==_ShootObjectType.Missile) StartCoroutine(MissileRoutine());
            if(type==_ShootObjectType.Effect) StartCoroutine(EffectRoutine());
        }
		public static Vector3 DrawIconAndName(Unit unit, float startX, float startY){
			float cachedX=startX;
			float cachedY=startY;
			
			EditorUtilities.DrawSprite(new Rect(startX, startY, 60, 60), unit.iconSprite);
			startX+=65;
			
			cont=new GUIContent("Name:", "The unit name to be displayed in game");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.unitName=EditorGUI.TextField(new Rect(startX+spaceX-65, startY, width-5, height), unit.unitName);
			
			cont=new GUIContent("Icon:", "The unit icon to be displayed in game, must be a sprite");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.iconSprite=(Sprite)EditorGUI.ObjectField(new Rect(startX+spaceX-65, startY, width-5, height), unit.iconSprite, typeof(Sprite), false);
			
			startX-=65;
			startY=cachedY;
			startX+=35+spaceX+width;	//startY+=20;
			cont=new GUIContent("HitPoint(HP):", "The unit default's HitPoint.\nThis is the base value to be modified by various in game bonus.");
			EditorGUI.LabelField(new Rect(startX, startY, width, height), cont);
			unit.defaultHP=EditorGUI.FloatField(new Rect(startX+80, startY, 40, height), unit.defaultHP);
			
			cont=new GUIContent(" - Regen:", "HP regeneration rate. The amount of HP to be regenerated per second");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.HPRegenRate=EditorGUI.FloatField(new Rect(startX+80, startY, 40, height), unit.HPRegenRate);
			
			if(unit.HPRegenRate<=0) GUI.color=new Color(0.5f, 0.5f, 0.5f, 1);
			cont=new GUIContent(" - Stagger:", "HP regeneration stagger duration(in second). The duration which the HP regen will be stopped when a unit is hit. Once the duration is passed the HP will start regenerating again");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.HPStaggerDuration=EditorGUI.FloatField(new Rect(startX+80, startY, 40, height), unit.HPStaggerDuration);
			GUI.color=Color.white;
			
			startY=cachedY; 	startX+=145;	
			cont=new GUIContent("Shield:", "The unit default's Shield. Shield can act as a regenerative damage absorber. A unit only be damaged once its shield has been depleted.\nThis is the base value to be modified by various in game bonus.");
			EditorGUI.LabelField(new Rect(startX, startY, width, height), cont);
			unit.defaultShield=EditorGUI.FloatField(new Rect(startX+70, startY, 40, height), unit.defaultShield);
			
			if(unit.defaultShield<=0) GUI.color=new Color(0.5f, 0.5f, 0.5f, 1);
			cont=new GUIContent(" - Regen:", "Shield regeneration rate. The amount of shield to be regenerated per second");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.shieldRegenRate=EditorGUI.FloatField(new Rect(startX+70, startY, 40, height), unit.shieldRegenRate);
			GUI.color=Color.white;
			
			if(unit.defaultShield<=0 || unit.shieldRegenRate<=0) GUI.color=new Color(0.5f, 0.5f, 0.5f, 1);
			cont=new GUIContent(" - Stagger:", "Shield regeneration stagger duration(in second). The duration which the shield regen will be stopped when a unit is hit. Once the duration is passed the shield will start regenerating again");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.shieldStaggerDuration=EditorGUI.FloatField(new Rect(startX+70, startY, 40, height), unit.shieldStaggerDuration);
			
			GUI.color=Color.white;
			
			
			float contentWidth=startX-cachedX+spaceX+25;
			
			//GUI.Box(new Rect(cachedX, cachedY, contentWidth, startY-cachedY+spaceY), "");
			
			return new Vector3(startX, startY+spaceY, contentWidth);
		}
		public static Vector3 DrawUnitDefensiveSetting(Unit unit, float startX, float startY, List<GameObject> objHList, string[] objHLabelList){
			//float cachedX=startX;
			//float cachedY=startY;
			
			string[] armorTypeLabel=EditorDBManager.GetArmorTypeLabel();
			cont=new GUIContent("Armor Type:", "The armor type of the unit\nArmor type can be configured in Damage Armor Table Editor");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.armorType=EditorGUI.Popup(new Rect(startX+spaceX, startY, width, height), unit.armorType, armorTypeLabel);
			
			int objID=GetObjectIDFromHList(unit.targetPoint, objHList);
			cont=new GUIContent("TargetPoint:", "The transform object which indicate the center point of the unit\nThis would be the point where the shootObject and effect will be aiming at");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			objID = EditorGUI.Popup(new Rect(startX+spaceX, startY, width, height), objID, objHLabelList);
			unit.targetPoint = (objHList[objID]==null) ? null : objHList[objID].transform;
			
			cont=new GUIContent("Hit Threshold:", "The range from the targetPoint where a shootObject is considered reached the target");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.hitThreshold=EditorGUI.FloatField(new Rect(startX+spaceX, startY, 40, height), unit.hitThreshold);
			
			cont=new GUIContent("Immuned to Crit:", "Check if the unit is immuned to critical hit");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.immuneToCrit=EditorGUI.Toggle(new Rect(startX+spaceX, startY, 40, height), unit.immuneToCrit);
			
			cont=new GUIContent("Immuned to Slow:", "Check if the unit is immuned to slow");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.immuneToSlow=EditorGUI.Toggle(new Rect(startX+spaceX, startY, 40, height), unit.immuneToSlow);
			
			cont=new GUIContent("Immuned to Stun:", "Check if the unit is immuned to stun");
			EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
			unit.immuneToStun=EditorGUI.Toggle(new Rect(startX+spaceX, startY, 40, height), unit.immuneToStun);
			
			return new Vector3(startX, startY, spaceX+width);
		}
Beispiel #5
0
 void OnUnitDestroyed(Unit unit)
 {
     if(currentTower==null) return;
     if(!unit.IsTower() || unit.GetUnitTower()!=currentTower) return;
     Hide();
 }
Beispiel #6
0
 public float GetDetectionRange(Unit tgtUnit)
 {
     return(GetAttackRange() + tgtUnit.GetRadius());
 }
 void OnUnitDestroyed(Unit unit)
 {
     if(unit.IsCreep()){
         if(unit.GetUnitCreep().lifeValue>0) GainLife(unit.GetUnitCreep().lifeValue);
     }
     else if(unit.IsTower()){
         if(unit.GetUnitTower()==selectedTower) _ClearSelectedTower();
     }
 }
Beispiel #8
0
		public static void NewUnit(Unit unit){ instance.StartCoroutine(instance._UnitOverlay(unit)); }
        void FPSHit(Unit hitUnit, Vector3 hitPoint)
        {
            if(attInstance.srcWeapon.GetAOERange()>0){
                LayerMask mask1=1<<LayerManager.LayerCreep();
                LayerMask mask2=1<<LayerManager.LayerCreepF();
                LayerMask mask = mask1 | mask2;

                Collider[] cols=Physics.OverlapSphere(hitPoint, attInstance.srcWeapon.GetAOERange(), mask);
                if(cols.Length>0){
                    List<Unit> tgtList=new List<Unit>();
                    for(int i=0; i<cols.Length; i++){
                        Unit unit=cols[i].gameObject.GetComponent<Unit>();
                        if(!unit.dead) tgtList.Add(unit);
                    }
                    if(tgtList.Count>0){
                        for(int i=0; i<tgtList.Count; i++){
                            AttackInstance attInst=new AttackInstance();
                            attInst.srcWeapon=attInstance.srcWeapon;
                            attInst.tgtUnit=tgtList[i];
                            attInst.Process();
                            tgtList[i].ApplyEffect(attInst);
                        }
                    }
                }
            }
            else{
                if(hitUnit!=null && hitUnit.IsCreep()){
                    attInstance.tgtUnit=hitUnit;
                    attInstance.Process();
                    hitUnit.ApplyEffect(attInstance);
                }
            }
        }
		void ScanForTarget(){
			if(!dead && !IsInConstruction() && !stunned){
				
				if(target==null){
					Collider[] cols=Physics.OverlapSphere(thisT.position, GetRange(), maskTarget);
					if(cols.Length>0){
						List<Unit> tgtList=new List<Unit>();
						for(int i=0; i<cols.Length; i++){
							Unit unit=cols[i].gameObject.GetComponent<Unit>();
							if(!unit.dead) tgtList.Add(unit);
						}
						
						
						if(tgtList.Count>0){
							if(targetPriority==_TargetPriority.Random) target=tgtList[Random.Range(0, tgtList.Count-1)];
							else if(targetPriority==_TargetPriority.Nearest){
								float nearest=Mathf.Infinity;
								for(int i=0; i<tgtList.Count; i++){
									float dist=Vector3.Distance(thisT.position, tgtList[i].thisT.position);
									if(dist<nearest){
										nearest=dist;
										target=tgtList[i];
									}
								}
							}
							else if(targetPriority==_TargetPriority.Weakest){
								float lowest=Mathf.Infinity;
								for(int i=0; i<tgtList.Count; i++){
									if(tgtList[i].HP<lowest){
										lowest=tgtList[i].HP;
										target=tgtList[i];
									}
								}
							}
							else if(targetPriority==_TargetPriority.Toughest){
								float highest=0;
								for(int i=0; i<tgtList.Count; i++){
									if(tgtList[i].HP>highest){
										highest=tgtList[i].HP;
										target=tgtList[i];
									}
								}
							}
							else if(targetPriority==_TargetPriority.First){
								target=tgtList[Random.Range(0, tgtList.Count-1)];
								float lowest=Mathf.Infinity;
								for(int i=0; i<tgtList.Count; i++){
									if(tgtList[i].GetDistFromDestination()<lowest){
										lowest=tgtList[i].GetDistFromDestination();
										target=tgtList[i];
									}
								}
							}
						}
					}
				}
				else{
					float dist=Vector3.Distance(thisT.position, target.thisT.position);
					if(target.dead || dist>GetRange()) target=null;
				}
			}
			
		}
Beispiel #11
0
		void OnUnitDestroyed(Unit unit){
			if(!unit.IsTower()) return;
			
			if(selectedTower==unit.GetUnitTower()) ClearSelectedTower();
		}
Beispiel #12
0
 public static void NewElectricityReciever(Unit unit)
 {
     instance.StartCoroutine(instance._ElectricityRecieverOverlay(unit));
 }
Beispiel #13
0
 public static void NewElectricity(Unit unit)
 {
     instance.StartCoroutine(instance._ElectricityValueOverlay(unit));
 }
Beispiel #14
0
        IEnumerator _ElectricityValueOverlay(Unit unit)
        {
            if (overlayedUnitList.Contains(unit)) yield break;

            overlayedUnitList.Add(unit);

            UnitOverlay overlay = GetUnusedOverlay();
            overlay.rootObj.SetActive(true);

            // if (unit.defaultShield > 0) overlay.barShield.gameObject.SetActive(true);
            // disable shield
            overlay.barShield.gameObject.SetActive(false);

            while (unit != null)
            {
                overlay.barHP.value = unit.electricityCurrentlyStored / unit.GetMaxElectricity();
                // if (unit.defaultShield > 0) overlay.barShield.value = unit.shield / unit.fullShield;

                Vector3 screenPos = mainCam.WorldToScreenPoint(unit.thisT.position + new Vector3(0, 0, 0));
                overlay.rootT.localPosition = screenPos + new Vector3(0, 20, 0);

                // if (overlay.barHP.value == 1 && overlay.barShield.value == 1) break;

                yield return null;
            }

            overlay.rootObj.SetActive(false);
            overlayedUnitList.Remove(unit);
        }
Beispiel #15
0
 void OnUnitDestroyed(Unit unit)
 {
     if(unit.IsCreep()){
         GainScore(unit.GetUnitCreep().scoreValue);
     }
     else if(unit.IsTower()){
         if(unit.GetUnitTower()==selectedTower) _ClearSelectedTower();
     }
 }
Beispiel #16
0
        void ScanForTarget()
        {
            if(dead || IsInConstruction() || stunned) return;

            //creeps changes direction so the scan direction for creep needs to be update
            if(directionalTargeting){
                if(IsCreep()) dirScanRot=thisT.rotation;
                else dirScanRot=thisT.rotation*Quaternion.Euler(0f, dirScanAngle, 0f);
            }

            if(directionalTargeting && scanDirT!=null) scanDirT.rotation=dirScanRot;

            if (shootOnlyAssignedTargets)
            {
                target = assignedTarget;
            }

            if(target==null){

                if (shootOnlyAssignedTargets)

                    return;

                Collider[] cols=Physics.OverlapSphere(thisT.position, GetRange(), maskTarget);

                if(cols.Length>0){
                    float minRange=GetRangeMin();

                    List<Unit> tgtList=new List<Unit>();
                    for(int i=0; i<cols.Length; i++){
                        if(minRange>0 && Vector3.Distance(cols[i].transform.position, thisT.position)<minRange){
                            continue;
                        }

                        Unit unit=cols[i].gameObject.GetComponent<Unit>();
                        if(!unit.dead) tgtList.Add(unit);
                    }

                    if(directionalTargeting){
                        List<Unit> filtered=new List<Unit>();
                        for(int i=0; i<tgtList.Count; i++){
                            Quaternion currentRot=Quaternion.LookRotation(tgtList[i].thisT.position-thisT.position);
                            if(Quaternion.Angle(dirScanRot, currentRot)<=dirScanFOV*0.5f) filtered.Add(tgtList[i]);
                        }
                        tgtList=filtered;
                    }

                    if(tgtList.Count>0){
                        if(targetPriority==_TargetPriority.Random) target=tgtList[Random.Range(0, tgtList.Count-1)];
                        else if(targetPriority==_TargetPriority.Nearest){
                            float nearest=Mathf.Infinity;
                            for(int i=0; i<tgtList.Count; i++){
                                float dist=Vector3.Distance(thisT.position, tgtList[i].thisT.position);
                                if(dist<nearest){
                                    nearest=dist;
                                    target=tgtList[i];
                                }
                            }
                        }
                        else if(targetPriority==_TargetPriority.Weakest){
                            float lowest=Mathf.Infinity;
                            for(int i=0; i<tgtList.Count; i++){
                                if(tgtList[i].HP<lowest){
                                    lowest=tgtList[i].HP;
                                    target=tgtList[i];
                                }
                            }
                        }
                        else if(targetPriority==_TargetPriority.Toughest){
                            float highest=0;
                            for(int i=0; i<tgtList.Count; i++){
                                if(tgtList[i].HP>highest){
                                    highest=tgtList[i].HP;
                                    target=tgtList[i];
                                }
                            }
                        }
                        else if(targetPriority==_TargetPriority.First){
                            target=tgtList[Random.Range(0, tgtList.Count-1)];
                            float lowest=Mathf.Infinity;
                            for(int i=0; i<tgtList.Count; i++){
                                if(tgtList[i].GetDistFromDestination()<lowest){
                                    lowest=tgtList[i].GetDistFromDestination();
                                    target=tgtList[i];
                                }
                            }
                        }
                    }
                }
                targetInLOS=false;
            }
            else{
                float dist=Vector3.Distance(thisT.position, target.thisT.position);
                if(target.dead || dist>GetRange()) target=null;

                if(target!=null && directionalTargeting){
                    Quaternion tgtRotation=Quaternion.LookRotation(target.thisT.position-thisT.position);
                    if(Quaternion.Angle(dirScanRot, tgtRotation)>=dirScanFOV*0.6f) target=null;
                }
            }
        }
Beispiel #17
0
        public IEnumerator TurretRoutine()
        {
            for(int i=0; i<shootPoints.Count; i++){
                if(shootPoints[i]==null){ shootPoints.RemoveAt(i);	i-=1;	}
            }

            if(shootPoints.Count==0){
                Debug.LogWarning("ShootPoint not assigned for unit - "+unitName+", auto assigned", this);
                shootPoints.Add(thisT);
            }

            for(int i=0; i<stats.Count; i++){
                if(stats[i].shootObjectT!=null) ObjectPoolManager.New(stats[i].shootObjectT.gameObject, 3);
            }

            yield return null;

            float t = Time.time;

            while(true){

                    while (shootingTime == 0 || target==null || stunned || IsInConstruction() || !targetInLOS) yield return null;
                turretOnCooldown=true;

                Unit currentTarget=target;

                float animationDelay=0;
                if(playShootAnimation!=null) animationDelay=playShootAnimation();
                if(animationDelay>0) yield return new WaitForSeconds(animationDelay);

                AttackInstance attInstance=new AttackInstance();
                attInstance.srcUnit=this;
                attInstance.tgtUnit=currentTarget;
                attInstance.Process();

                for(int i=0; i<shootPoints.Count; i++){
                    Transform sp=shootPoints[i];

                    Transform objT = null;
                    if (usePoolForShootObjects)
                    {
                        objT = (Transform)ObjectPoolManager.Spawn(GetShootObjectT(), sp.position, sp.rotation);
                    }
                    else
                    {
                        objT = (Transform)Instantiate(GetShootObjectT(), sp.position, sp.rotation);
                    }

                    ShootObject shootObj=objT.GetComponent<ShootObject>();
                    shootObj.Shoot(attInstance, sp);

                    if(delayBetweenShootPoint>0) yield return new WaitForSeconds(delayBetweenShootPoint);
                }

                yield return new WaitForSeconds(GetCooldown()-animationDelay-shootPoints.Count*delayBetweenShootPoint);

                if(GameControl.ResetTargetAfterShoot()) target=null;
                turretOnCooldown=false;
            }
        }
		void OnUnitDestroyed(Unit unit){
			if(unit.IsTower() && towerDestroyedSound!=null) _PlaySound(towerDestroyedSound); 
		}
Beispiel #19
0
 public static void OnUnitDestroyed(Unit unit)
 {
     if (unit.IsCreep())
     {
         if (onCreepDestroyedE != null) onCreepDestroyedE(unit.GetUnitCreep());
     }
     else if (!unit.IsTower())
     {
         if (onTowerDestroyedE != null) onTowerDestroyedE(unit.GetUnitTower());
     }
 }
		//called when an ability is fired, reduce the energy, start the cooldown and what not
		public void ActivateAbility(Ability ab, Vector3 pos=default(Vector3), Unit unit=null){
			ab.usedCount+=1;
			energy-=ab.GetCost();
			StartCoroutine(ab.CooldownRoutine());
			
			CastAbility(ab, pos, unit);
			
			if(onAbilityActivatedE!=null) onAbilityActivatedE(ab);
		}
		//called from ActivateAbility, cast the ability, visual effect and actual effect goes here
		public void CastAbility(Ability ab, Vector3 pos, Unit unit=null){
			if(ab.effectObj!=null){
				ObjectPoolManager.Spawn(ab.effectObj, pos, Quaternion.identity);
			}
			
			if(ab.useDefaultEffect){
				StartCoroutine(ApplyAbilityEffect(ab, pos, unit));
			}
		}
		//apply the ability effect, damage, stun, buff and so on 
		IEnumerator ApplyAbilityEffect(Ability ab, Vector3 pos, Unit tgtUnit=null){
			yield return new WaitForSeconds(ab.effectDelay);
			
			LayerMask mask1=1<<LayerManager.LayerTower();
			LayerMask mask2=1<<LayerManager.LayerCreep();
			LayerMask mask3=1<<LayerManager.LayerCreepF();
			LayerMask mask=mask1 | mask2 | mask3;
			
			List<Unit> creepList=new List<Unit>();
			List<Unit> towerList=new List<Unit>();
			
			if(tgtUnit==null){
				float radius=ab.requireTargetSelection ? ab.GetAOERadius() : Mathf.Infinity;
				Collider[] cols=Physics.OverlapSphere(pos, radius, mask);
				
				if(cols.Length>0){
					for(int i=0; i<cols.Length; i++){
						Unit unit=cols[i].gameObject.GetComponent<Unit>();
						if(unit.unitC!=null) creepList.Add(unit.unitC);
						if(unit.unitT!=null) towerList.Add(unit.unitT);
					}
				}
			}
			else{
				creepList.Add(tgtUnit);
				towerList.Add(tgtUnit);
			}
				
			AbilityEffect eff=ab.GetActiveEffect();
			
			for(int n=0; n<creepList.Count; n++){
				if(eff.damageMax>0){
					creepList[n].ApplyDamage(Random.Range(eff.damageMin, eff.damageMax));
				}
				else if(eff.stunChance>0 && eff.duration>0){
					if(Random.Range(0f, 1f)<eff.stunChance) creepList[n].ApplyStun(eff.duration);
				}
				else if(eff.slow.IsValid()){
					creepList[n].ApplySlow(eff.slow);
				}
				else if(eff.dot.GetTotalDamage()>0){
					creepList[n].ApplyDot(eff.dot);
				}
			}
			for(int n=0; n<towerList.Count; n++){
				if(eff.duration>0){
					if(eff.damageBuff>0){
						towerList[n].ABBuffDamage(eff.damageBuff, eff.duration);
					}
					else if(eff.rangeBuff>0){
						towerList[n].ABBuffRange(eff.rangeBuff, eff.duration);
					}
					else if(eff.cooldownBuff>0){
						towerList[n].ABBuffCooldown(eff.cooldownBuff, eff.duration);
					}
				}
				else if(eff.HPGainMax>0){
					towerList[n].RestoreHP(Random.Range(eff.HPGainMin, eff.HPGainMax));
				}
			}
			
		}
        void OnUnitDestroyed(Unit unit)
        {
            if(!unit.IsCreep()) return;

            UnitCreep creep=unit.GetUnitCreep();
            OnUnitCleared(creep);
        }
Beispiel #24
0
        public void ScanForTarget()
        {
            if (attackTarget != null)
            {
                if (attackTarget.IsDestroyed())
                {
                    attackTarget = null;
                }
                else
                {
                    float dist = Vector3.Distance(GetPos(), attackTarget.GetPos());
                    if (dist > GetDetectionRange(attackTarget))
                    {
                        attackTarget = null;
                    }
                    else
                    {
                        return;
                    }
                }
            }

            if (CreepIsOnAttackCD())
            {
                return;                                 //for creep only
            }
            //if(cooldownAttack>0) return;

            List <Unit> unitList = null;

            if (IsTower())
            {
                unitList = SpawnManager.GetUnitsWithinRange(this, GetAttackRange(), GetTargetGroup());
            }
            else
            {
                unitList = TowerManager.GetUnitsWithinRange(this, GetAttackRange());
            }

            if (targetingFov > 0 && targetingFov < 360)
            {
                Quaternion curDir = thisT.rotation * Quaternion.Euler(0, targetingDir, 0);
                for (int i = 0; i < unitList.Count; i++)
                {
                    Quaternion dirToTarget = Quaternion.LookRotation(unitList[i].GetPos() - GetPos());
                    if (Quaternion.Angle(curDir, dirToTarget) > targetingFov * 0.5f)
                    {
                        unitList.RemoveAt(i);      i -= 1;
                    }
                }
            }

            if (unitList.Count <= 0)
            {
                return;
            }

            if (IsCreep() && targetMode == _TargetMode.NearestToDestination)
            {
                targetMode = _TargetMode.Random;
            }

            int newTargetIdx = -1;

            if (unitList.Count == 1)
            {
                newTargetIdx = 0;
            }
            else if (targetMode == _TargetMode.Random)
            {
                newTargetIdx = Random.Range(0, unitList.Count);
            }
            else if (targetMode == _TargetMode.NearestToSelf)
            {
                float nearest = Mathf.Infinity;
                for (int i = 0; i < unitList.Count; i++)
                {
                    float dist = Vector3.Distance(GetPos(), unitList[i].GetPos());
                    if (dist < nearest)
                    {
                        newTargetIdx = i; nearest = dist;
                    }
                }
            }
            else if (targetMode == _TargetMode.MostHP)
            {
                float mostHP = 0;
                for (int i = 0; i < unitList.Count; i++)
                {
                    if (unitList[i].hp + unitList[i].sh > mostHP)
                    {
                        newTargetIdx = i; mostHP = unitList[i].hp + unitList[i].sh;
                    }
                }
            }
            else if (targetMode == _TargetMode.LeastHP)
            {
                float leastHP = Mathf.Infinity;
                for (int i = 0; i < unitList.Count; i++)
                {
                    if (unitList[i].hp + unitList[i].sh < leastHP)
                    {
                        newTargetIdx = i; leastHP = unitList[i].hp + unitList[i].sh;
                    }
                }
            }
            else if (targetMode == _TargetMode.NearestToDestination)
            {
                float pathDist = Mathf.Infinity; int furthestWP = 0; int furthestSubWP = 0; float distToDest = Mathf.Infinity;
                for (int i = 0; i < unitList.Count; i++)
                {
                    float pDist         = unitList[i].GetPathDist();
                    int   wpIdx         = unitList[i].GetWPIdx();
                    int   subWpIdx      = unitList[i].GetSubWPIdx();
                    float tgtDistToDest = unitList[i].GetDistToTargetPos();

                    if (pDist < pathDist)
                    {
                        newTargetIdx = i; pathDist = pDist; furthestWP = wpIdx; furthestSubWP = subWpIdx; distToDest = tgtDistToDest;
                    }
                    else if (pDist == pathDist)
                    {
                        if (furthestWP < wpIdx)
                        {
                            newTargetIdx = i; pathDist = pDist; furthestWP = wpIdx; furthestSubWP = subWpIdx; distToDest = tgtDistToDest;
                        }
                        else if (furthestWP == wpIdx)
                        {
                            if (furthestSubWP < subWpIdx)
                            {
                                newTargetIdx = i; pathDist = pDist; furthestWP = wpIdx; furthestSubWP = subWpIdx; distToDest = tgtDistToDest;
                            }
                            else if (furthestSubWP == subWpIdx && tgtDistToDest < distToDest)
                            {
                                newTargetIdx = i; pathDist = pDist; furthestWP = wpIdx; furthestSubWP = subWpIdx; distToDest = tgtDistToDest;
                            }
                        }
                    }
                }
            }


            if (newTargetIdx >= 0)
            {
                attackTarget = unitList[newTargetIdx];
                if (snapAiming)
                {
                    Aim();
                }
            }
        }