public virtual AttackableUnit GetTarget() { AttackableUnit result = null; var mode = ActiveMode; if (ActiveMode == OrbwalkingMode.Flee || ActiveMode == OrbwalkingMode.WallJump) { return(null); } if ((mode == OrbwalkingMode.Mixed || mode == OrbwalkingMode.LaneClear) && !Menu.Item("PriorizeFarm").GetValue <bool>()) { var target = TargetSelector.GetTarget(-1, TargetSelector.DamageType.Physical); if (target != null && InAutoAttackRange(target)) { return(target); } } var attackGankPlankBarrels = Menu.Item("AttackGPBarrel").GetValue <StringList>().SelectedIndex; if (attackGankPlankBarrels != 2 && (attackGankPlankBarrels == 0 || mode == OrbwalkingMode.LaneClear || mode == OrbwalkingMode.Mixed || mode == OrbwalkingMode.LastHit || mode == OrbwalkingMode.Freeze)) { var enemyGangPlank = HeroManager.Enemies.FirstOrDefault( e => e.ChampionName.Equals("gangplank", StringComparison.InvariantCultureIgnoreCase)); if (enemyGangPlank != null) { var barrels = Get <Obj_AI_Minion>() .Where( minion => minion.Team == GameObjectTeam.Neutral && minion.CharData.BaseSkinName == "gangplankbarrel" && minion.IsHPBarRendered && minion.IsValidTarget() && InAutoAttackRange(minion)); var objAiMinions = barrels as Obj_AI_Minion[] ?? barrels.ToArray(); foreach (var barrel in objAiMinions) { if (barrel.Health <= 1f) { return(barrel); } var t = (int)(player.AttackCastDelay * 1000) + Game.Ping / 2 + 1000 * (int)Math.Max(0, player.Distance(barrel) - player.BoundingRadius) / (int)GetMyProjectileSpeed(); var barrelBuff = barrel.Buffs.FirstOrDefault( b => b.Name.Equals("gangplankebarrelactive", StringComparison.InvariantCultureIgnoreCase)); if (barrelBuff != null && barrel.Health <= 2f) { var healthDecayRate = enemyGangPlank.Level >= 13 ? 0.5f : (enemyGangPlank.Level >= 7 ? 1f : 2f); var nextHealthDecayTime = Game.Time < barrelBuff.StartTime + healthDecayRate ? barrelBuff.StartTime + healthDecayRate : barrelBuff.StartTime + healthDecayRate * 2; if (nextHealthDecayTime <= Game.Time + t / 1000f) { return(barrel); } } } if (objAiMinions.Any()) { return(null); } } } if (mode == OrbwalkingMode.LaneClear || mode == OrbwalkingMode.Mixed || mode == OrbwalkingMode.LastHit || mode == OrbwalkingMode.Freeze) { var MinionList = Get <Obj_AI_Minion>() .Where(minion => minion.IsValidTarget() && InAutoAttackRange(minion)) .OrderByDescending(minion => minion.CharData.BaseSkinName.Contains("Siege")) .ThenBy(minion => minion.CharData.BaseSkinName.Contains("Super")) .ThenBy(minion => minion.Health) .ThenByDescending(minion => minion.MaxHealth); foreach (var minion in MinionList) { var t = (int)(player.AttackCastDelay * 1000) - 100 + Game.Ping / 2 + 1000 * (int)Math.Max(0, player.Distance(minion) - player.BoundingRadius) / (int)GetMyProjectileSpeed(); if (mode == OrbwalkingMode.Freeze) { t += 200 + Game.Ping / 2; } var predHealth = HealthPrediction.GetHealthPrediction(minion, t, FarmDelay); if (minion.Team != GameObjectTeam.Neutral && ShouldAttackMinion(minion)) { var damage = player.GetAutoAttackDamage(minion, true); var killable = predHealth <= damage; if (mode == OrbwalkingMode.Freeze) { if (minion.Health < 50 || predHealth <= 50) { return(minion); } } else { if (predHealth <= 0) { FireOnNonKillableMinion(minion); } if (killable) { return(minion); } } } } } if (_forcedTarget.IsValidTarget() && InAutoAttackRange(_forcedTarget)) { return(_forcedTarget); } if (mode == OrbwalkingMode.LaneClear && (!Menu.Item("FocusMinionsOverTurrets").GetValue <KeyBind>().Active || !MinionManager.GetMinions(ObjectManager.Player.Position, GetRealAutoAttackRange(ObjectManager.Player)).Any())) { foreach (var turret in Get <Obj_AI_Turret>().Where(t => t.IsValidTarget() && InAutoAttackRange(t))) { return(turret); } foreach ( var turret in Get <Obj_BarracksDampener>().Where(t => t.IsValidTarget() && InAutoAttackRange(t))) { return(turret); } foreach (var nexus in Get <Obj_HQ>().Where(t => t.IsValidTarget() && InAutoAttackRange(t))) { return(nexus); } } if (mode != OrbwalkingMode.LastHit) { if (mode != OrbwalkingMode.LaneClear || !ShouldWait()) { var target = TargetSelector.GetTarget(-1, TargetSelector.DamageType.Physical); if (target.IsValidTarget() && InAutoAttackRange(target)) { return(target); } } } if (mode == OrbwalkingMode.LaneClear || mode == OrbwalkingMode.Mixed) { var jminions = Get <Obj_AI_Minion>() .Where( mob => mob.IsValidTarget() && mob.Team == GameObjectTeam.Neutral && InAutoAttackRange(mob) && mob.CharData.BaseSkinName != "gangplankbarrel" && mob.Name != "WardCorpse"); result = Menu.Item("Smallminionsprio").GetValue <bool>() ? jminions.MinOrDefault(mob => mob.MaxHealth) : jminions.MaxOrDefault(mob => mob.MaxHealth); if (result != null) { return(result); } } if (mode == OrbwalkingMode.LaneClear || mode == OrbwalkingMode.Mixed || mode == OrbwalkingMode.LastHit || mode == OrbwalkingMode.Freeze) { var closestTower = Get <Obj_AI_Turret>() .MinOrDefault(t => t.IsAlly && !t.IsDead ? player.Distance(t, true) : float.MaxValue); if (closestTower != null && player.Distance(closestTower, true) < 1500 * 1500) { Obj_AI_Minion farmUnderTurretMinion = null; Obj_AI_Minion noneKillableMinion = null; var minions = MinionManager.GetMinions(player.Position, player.AttackRange + 200) .Where(minion => InAutoAttackRange(minion) && closestTower.Distance(minion, true) < 900 * 900) .OrderByDescending(minion => minion.CharData.BaseSkinName.Contains("Siege")) .ThenBy(minion => minion.CharData.BaseSkinName.Contains("Super")) .ThenByDescending(minion => minion.MaxHealth) .ThenByDescending(minion => minion.Health); if (minions.Any()) { var turretMinion = minions.FirstOrDefault( minion => minion is Obj_AI_Minion && HealthPrediction.HasTurretAggro((Obj_AI_Minion)minion)); if (turretMinion != null) { var hpLeftBeforeDie = 0; var hpLeft = 0; var turretAttackCount = 0; var turretStarTick = HealthPrediction.TurretAggroStartTick(turretMinion as Obj_AI_Minion); var turretLandTick = turretStarTick + (int)(closestTower.AttackCastDelay * 1000) + 1000 * Math.Max(0, (int) (turretMinion.Distance(closestTower) - closestTower.BoundingRadius)) / (int)(closestTower.BasicAttack.MissileSpeed + 70); for (float i = turretLandTick + 50; i < turretLandTick + 10 * closestTower.AttackDelay * 1000 + 50; i = i + closestTower.AttackDelay * 1000) { var time = (int)i - Utils.GameTimeTickCount + Game.Ping / 2; var predHP = (int) HealthPrediction.LaneClearHealthPrediction(turretMinion, time > 0 ? time : 0); if (predHP > 0) { hpLeft = predHP; turretAttackCount += 1; continue; } hpLeftBeforeDie = hpLeft; hpLeft = 0; break; } if (hpLeft == 0 && turretAttackCount != 0 && hpLeftBeforeDie != 0) { var damage = (int)player.GetAutoAttackDamage(turretMinion, true); var hits = hpLeftBeforeDie / damage; var timeBeforeDie = turretLandTick + (turretAttackCount + 1) * (int)(closestTower.AttackDelay * 1000) - Utils.GameTimeTickCount; var timeUntilAttackReady = LastAATick + (int)(player.AttackDelay * 1000) > Utils.GameTimeTickCount + Game.Ping / 2 + 25 ? LastAATick + (int)(player.AttackDelay * 1000) - (Utils.GameTimeTickCount + Game.Ping / 2 + 25) : 0; var timeToLandAttack = player.IsMelee ? player.AttackCastDelay * 1000 : player.AttackCastDelay * 1000 + 1000 * Math.Max(0, turretMinion.Distance(player) - player.BoundingRadius) / player.BasicAttack.MissileSpeed; if (hits >= 1 && hits * player.AttackDelay * 1000 + timeUntilAttackReady + timeToLandAttack < timeBeforeDie) { farmUnderTurretMinion = turretMinion as Obj_AI_Minion; } else if (hits >= 1 && hits * player.AttackDelay * 1000 + timeUntilAttackReady + timeToLandAttack > timeBeforeDie) { noneKillableMinion = turretMinion as Obj_AI_Minion; } } else if (hpLeft == 0 && turretAttackCount == 0 && hpLeftBeforeDie == 0) { noneKillableMinion = turretMinion as Obj_AI_Minion; } if (ShouldWaitUnderTurret(noneKillableMinion)) { return(null); } if (farmUnderTurretMinion != null) { return(farmUnderTurretMinion); } foreach ( var minion in minions.Where( x => x.NetworkId != turretMinion.NetworkId && x is Obj_AI_Minion && !HealthPrediction.HasMinionAggro((Obj_AI_Minion)x))) { var playerDamage = (int)player.GetAutoAttackDamage(minion); var turretDamage = (int)closestTower.GetAutoAttackDamage(minion, true); var leftHP = (int)minion.Health % turretDamage; if (leftHP > playerDamage) { return(minion); } } var lastminion = minions.LastOrDefault( x => x.NetworkId != turretMinion.NetworkId && x is Obj_AI_Minion && !HealthPrediction.HasMinionAggro((Obj_AI_Minion)x)); if (lastminion != null && minions.Count() >= 2) { if (1f / player.AttackDelay >= 1f && (int)(turretAttackCount * closestTower.AttackDelay / player.AttackDelay) * player.GetAutoAttackDamage(lastminion) > lastminion.Health) { return(lastminion); } if (minions.Count() >= 5 && 1f / player.AttackDelay >= 1.2) { return(lastminion); } } } else { if (ShouldWaitUnderTurret(noneKillableMinion)) { return(null); } foreach ( var minion in minions.Where( x => x is Obj_AI_Minion && !HealthPrediction.HasMinionAggro((Obj_AI_Minion)x))) { { var playerDamage = (int)player.GetAutoAttackDamage(minion); var turretDamage = (int)closestTower.GetAutoAttackDamage(minion, true); var leftHP = (int)minion.Health % turretDamage; if (leftHP > playerDamage) { return(minion); } } } var lastminion = minions.LastOrDefault( x => x is Obj_AI_Minion && !HealthPrediction.HasMinionAggro((Obj_AI_Minion)x)); if (lastminion == null || minions.Count() < 2) { return(null); } if (minions.Count() >= 5 && 1f / player.AttackDelay >= 1.2) { return(lastminion); } } return(null); } } } if (mode == OrbwalkingMode.LaneClear) { if (!ShouldWait()) { if (_prevMinion.IsValidTarget() && InAutoAttackRange(_prevMinion)) { var predHealth = HealthPrediction.LaneClearHealthPrediction(_prevMinion, (int)(player.AttackDelay * 1000 * LaneClearWaitTimeMod), FarmDelay); if (predHealth >= 2 * player.GetAutoAttackDamage(_prevMinion) || Math.Abs(predHealth - _prevMinion.Health) < float.Epsilon) { return(_prevMinion); } } result = Get <Obj_AI_Minion>() .Where( minion => minion.IsValidTarget() && InAutoAttackRange(minion) && ShouldAttackMinion(minion)) .Select( minion => new { minion, predHealth = HealthPrediction.LaneClearHealthPrediction(minion, (int)(player.AttackDelay * 1000 * LaneClearWaitTimeMod), FarmDelay) }) .Where( t => t.predHealth >= 2 * player.GetAutoAttackDamage(t.minion) || Math.Abs(t.predHealth - t.minion.Health) < float.Epsilon) .Select(t => t.minion) .MaxOrDefault(m => !MinionManager.IsMinion(m, true) ? float.MaxValue : m.Health); if (result != null) { _prevMinion = (Obj_AI_Minion)result; } } } return(result); }