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); }
void OnUnitDestroyed(Unit unit) { if(currentTower==null) return; if(!unit.IsTower() || unit.GetUnitTower()!=currentTower) return; Hide(); }
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(); } }
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; } } }
void OnUnitDestroyed(Unit unit){ if(!unit.IsTower()) return; if(selectedTower==unit.GetUnitTower()) ClearSelectedTower(); }
public static void NewElectricityReciever(Unit unit) { instance.StartCoroutine(instance._ElectricityRecieverOverlay(unit)); }
public static void NewElectricity(Unit unit) { instance.StartCoroutine(instance._ElectricityValueOverlay(unit)); }
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); }
void OnUnitDestroyed(Unit unit) { if(unit.IsCreep()){ GainScore(unit.GetUnitCreep().scoreValue); } else if(unit.IsTower()){ if(unit.GetUnitTower()==selectedTower) _ClearSelectedTower(); } }
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; } } }
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); }
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); }
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(); } } }