Пример #1
0
        public Tree GetChaseTree(
            Vector3 hero,
            Target target,
            TimberChain timberChain,
            float maxDistanceToEnemy,
            float minDistanceToHero)
        {
            var castRange      = timberChain.GetCastRange();
            var targetPosition = target.GetPosition();

            var targetDistance    = target.GetDistance(hero);
            var ignoreMaxDistance = targetDistance > castRange + 200;

            var trees = GetAvailableTrees(hero, targetPosition, castRange).ToList();

            return
                (trees.Where(
                     x =>
                     (ignoreMaxDistance ||
                      x.Distance2D(
                          TimberPrediction.PredictedXYZ(
                              target,
                              timberChain.CastPoint + x.Distance2D(targetPosition) / timberChain.Speed))
                      <= maxDistanceToEnemy ||
                      (Math.Abs(
                           target.Hero.FindAngleR() - Utils.DegreeToRadian(target.Hero.FindAngleForTurnTime(x.Position)))
                       < 0.3 && x.Distance2D(targetPosition) < targetDistance)) &&
                     x.Distance2D(hero) >= minDistanceToHero)
                 .FirstOrDefault(
                     z =>
                     trees.Where(x => !x.Equals(z))
                     .All(x => !IsPointOnLine(x.Position, hero, z.Position, forceRadius: 25))));
        }
Пример #2
0
        public Tree GetChaseTree(
            Hero hero,
            Target target,
            TimberChain timberChain,
            float maxDistanceToEnemy,
            float minDistanceToHero)
        {
            var castRange      = timberChain.GetCastRange();
            var targetPosition = target.GetPosition();

            var targetDistance    = target.GetDistance(hero.Position);
            var ignoreMaxDistance = targetDistance > castRange + 200;

            var delay = Game.RawGameTime + timberChain.CastPoint + Game.Ping / 1000;
            var trees = GetAvailableTrees(hero, targetPosition, castRange, delay, timberChain.Speed).ToList();

            return
                (trees.Where(
                     x =>
                     (ignoreMaxDistance ||
                      x.Distance2D(
                          TimberPrediction.PredictedXYZ(
                              target,
                              timberChain.CastPoint + x.Distance2D(targetPosition) / timberChain.Speed))
                      <= maxDistanceToEnemy ||
                      (target.Hero.GetTurnTime(x.Position) <= 0 && x.Distance2D(targetPosition) < 600)) &&
                     x.Distance2D(hero) >= minDistanceToHero)
                 .FirstOrDefault(
                     z =>
                     trees.Where(x => !x.Equals(z))
                     .All(
                         x =>
                         x.Distance2D(hero) > 150 && !IsPointOnLine(x.Position, hero.Position, z.Position, 25))));
        }
Пример #3
0
        public Vector3 GetPosition(bool forDrawing = false)
        {
            if (Hero == null)
            {
                return(new Vector3());
            }

            if (IsVsisible)
            {
                MovementSpeed = Hero.MovementSpeed;
                lastVisible   = Game.RawGameTime;
                return(forDrawing ? Hero.Position : Hero.NetworkPosition);
            }

            return(TimberPrediction.IsIdle(Hero) ? Position : Prediction.InFront(Hero, MovementSpeed * GetInvisTime()));
        }
Пример #4
0
        public void OnLoad()
        {
            hero        = ObjectManager.LocalHero;
            menuManager = new MenuManager(hero.Name);
            treeFactory = new TreeFactory();
            orbwalker   = new Orbwalker(hero);
            sleeper     = new MultiSleeper();

            TimberPrediction.OnLoad();

            whirlingDeath = new WhirlingDeath(hero.Spellbook.SpellQ);
            timberChain   = new TimberChain(hero.Spellbook.SpellW);

            chakrams.Add(
                new Chakram(
                    hero.Spellbook.Spells.First(x => x.Name == "shredder_chakram"),
                    hero.Spellbook.Spells.First(x => x.Name == "shredder_return_chakram")));
        }
Пример #5
0
 public void OnClose()
 {
     menuManager.OnClose();
     chakrams.Clear();
     TimberPrediction.OnClose();
 }
Пример #6
0
        public void OnUpdate()
        {
            if (sleeper.Sleeping(this))
            {
                return;
            }

            if (Game.IsPaused || !hero.IsAlive || hero.IsChanneling() || !menuManager.IsEnabled)
            {
                return;
            }

            var heroPosition = hero.Position;

            if (!aghsAdded && !sleeper.Sleeping(chakrams))
            {
                if (hero.AghanimState())
                {
                    chakrams.Add(
                        new Chakram(
                            hero.Spellbook.Spells.First(x => x.Name == "shredder_chakram_2"),
                            hero.Spellbook.Spells.First(x => x.Name == "shredder_return_chakram_2")));
                    aghsAdded = true;
                }
                sleeper.Sleep(5000, chakrams);
            }

            if (menuManager.MoveEnabled)
            {
                var blink         = hero.FindItem("item_blink", true);
                var mousePosition = Game.MousePosition;

                if (blink != null && !sleeper.Sleeping(blink) && menuManager.IsItemEnabled(blink.StoredName()) &&
                    blink.CanBeCasted() && mousePosition.Distance2D(hero) > 500)
                {
                    var castRange = blink.GetCastRange();

                    var blinkPosition = hero.Distance2D(mousePosition) > castRange
                                            ? (mousePosition - heroPosition) * castRange
                                        / mousePosition.Distance2D(hero) + heroPosition
                                            : mousePosition;

                    blink.UseAbility(blinkPosition);
                    sleeper.Sleep(1000, blink);
                }
                else if (timberChain.CanBeCasted())
                {
                    var moveTree = treeFactory.GetMoveTree(hero, mousePosition, timberChain.GetCastRange(), 800);

                    if (moveTree != null)
                    {
                        timberChain.UseAbility(moveTree.Position);
                        sleeper.Sleep(
                            timberChain.GetSleepTime + moveTree.Distance2D(hero) / timberChain.Speed * 1000 * 2
                            + Game.Ping,
                            this);
                        return;
                    }
                }

                if (!sleeper.Sleeping(hero))
                {
                    hero.Move(mousePosition);
                    sleeper.Sleep(200, hero);
                }
            }
            else if (menuManager.ChaseEnabled)
            {
                if (!target.IsValid())
                {
                    return;
                }

                if (!target.Locked)
                {
                    target.Locked = true;
                }

                if (!cameraCentered && menuManager.IsCenterCameraEnabled)
                {
                    Game.ExecuteCommand("+dota_camera_center_on_hero");
                    cameraCentered = true;
                }

                var distanceToEnemy = target.GetDistance(heroPosition);
                var targetPosition  = target.GetPosition();
                var ping            = Game.Ping;

                var phaseChakram = chakrams.FirstOrDefault(x => x.IsInPhase);

                if (phaseChakram != null)
                {
                    var predictedPosition = TimberPrediction.PredictedXYZ(
                        hero,
                        target,
                        distanceToEnemy / phaseChakram.Speed * 1000);

                    if (phaseChakram.Position.Distance2D(predictedPosition) > phaseChakram.Radius)
                    {
                        phaseChakram.Stop(hero);
                        treeFactory.ClearUnavailableTrees(true);
                        sleeper.Sleep(ping + 100, this);
                        return;
                    }
                }

                if (timberChain.IsInPhase && timberChain.CastedOnEnemy)
                {
                    var predictedPosition = TimberPrediction.PredictedXYZ(
                        hero,
                        target,
                        distanceToEnemy / timberChain.Speed * 1000);

                    if (timberChain.Position.Distance2D(predictedPosition) > timberChain.Radius)
                    {
                        timberChain.Stop(hero);
                        timberChain.ChakramCombo = false;
                        whirlingDeath.Combo      = false;
                        sleeper.Sleep(ping + 100, this);
                        return;
                    }
                }

                var doubleChakramDamage = chakrams.Count(x => x.Damaging(target)) == 2;
                var returnChakrams      = chakrams.Where(x => x.ShouldReturn(hero, target, doubleChakramDamage));

                foreach (var chakram in returnChakrams)
                {
                    chakram.Return();
                    treeFactory.ClearUnavailableTrees(true);
                }

                var blink       = hero.FindItem("item_blink", true);
                var shivasGuard = hero.FindItem("item_shivas_guard", true);
                var soulRing    = hero.FindItem("item_soul_ring");

                var usableChakram = chakrams.FirstOrDefault(x => x.CanBeCasted());

                if (blink != null && !sleeper.Sleeping(blink) && menuManager.IsItemEnabled(blink.StoredName()) &&
                    blink.CanBeCasted() && distanceToEnemy > 500 &&
                    (target.FindAngle(heroPosition) > 0.6 || distanceToEnemy > 700) &&
                    (timberChain.Cooldown > 2 || distanceToEnemy > 800) &&
                    (whirlingDeath.CanBeCasted() || usableChakram != null) &&
                    hero.Modifiers.All(x => x.Name != timberChain.ModifierName) && !timberChain.IsSleeping)
                {
                    var castRange = blink.GetCastRange();

                    var sleep = ping + 300;

                    if (distanceToEnemy <= castRange)
                    {
                        var positionNearTree = treeFactory.GetBlinkPosition(
                            target,
                            heroPosition,
                            castRange,
                            whirlingDeath.Radius,
                            whirlingDeath.CanBeCasted());

                        sleep += (float)hero.GetTurnTime(positionNearTree);
                        blink.UseAbility(positionNearTree);
                    }
                    else
                    {
                        var maxDistancePosition =
                            (targetPosition - heroPosition) * castRange / targetPosition.Distance2D(hero)
                            + heroPosition;

                        sleep += (float)hero.GetTurnTime(maxDistancePosition);
                        blink.UseAbility(maxDistancePosition);
                    }
                    sleeper.Sleep(1000, blink);
                    sleeper.Sleep(sleep, this);
                    return;
                }

                if (soulRing != null && !sleeper.Sleeping(soulRing) && menuManager.IsItemEnabled(soulRing.StoredName()) &&
                    soulRing.CanBeCasted() && hero.Health > 600)
                {
                    soulRing.UseAbility();
                    sleeper.Sleep(1000, soulRing);
                }

                if (shivasGuard != null && !sleeper.Sleeping(shivasGuard) &&
                    menuManager.IsItemEnabled(shivasGuard.StoredName()) && shivasGuard.CanBeCasted() &&
                    distanceToEnemy < 500)
                {
                    shivasGuard.UseAbility();
                    sleeper.Sleep(1000, shivasGuard);
                }

                if (whirlingDeath.CanBeCasted() && (distanceToEnemy <= whirlingDeath.Radius ||
                                                    whirlingDeath.Combo && whirlingDeath.ComboDelayPassed))
                {
                    whirlingDeath.UseAbility();
                    whirlingDeath.Combo      = false;
                    timberChain.ChakramCombo = false;
                }

                if (timberChain.CanBeCasted() && (usableChakram == null || distanceToEnemy > 300))
                {
                    if ((blink == null || !blink.CanBeCasted() || !menuManager.IsItemEnabled(blink.Name)) &&
                        usableChakram != null && !chakrams.Any(x => x.IsSleeping || x.Casted) &&
                        distanceToEnemy < chakrams.First().GetCastRange() &&
                        treeFactory.TreesInPath(hero, targetPosition, 100) >= 5)
                    {
                        var predictedPosition = TimberPrediction.PredictedXYZ(
                            hero,
                            target,
                            usableChakram.GetSleepTime + ping
                            + target.GetDistance(heroPosition) / usableChakram.Speed * 1000
                            + usableChakram.Radius / 2 / target.Hero.MovementSpeed * 1000);

                        usableChakram.UseAbility(predictedPosition, target.Hero, hero);
                        treeFactory.SetUnavailableTrees(hero.Position, predictedPosition, usableChakram);

                        sleeper.Sleep(usableChakram.GetSleepTime + ping, this);
                        return;
                    }

                    var possibleDamageTree = treeFactory.GetDamageTree(hero, targetPosition, timberChain);

                    if (target.IsVsisible && possibleDamageTree != null)
                    {
                        var predictedPosition = TimberPrediction.PredictedXYZ(
                            hero,
                            target,
                            timberChain.CastPoint * 1000
                            + (distanceToEnemy + hero.Distance2D(possibleDamageTree.Position)) / timberChain.Speed
                            * 1000 + ping);

                        var damageTreeWithPrediction = treeFactory.GetDamageTree(
                            hero,
                            predictedPosition,
                            timberChain,
                            blink != null && !sleeper.Sleeping(blink) && menuManager.IsItemEnabled(blink.Name) &&
                            blink.CanBeCasted());

                        if (damageTreeWithPrediction != null)
                        {
                            timberChain.UseAbility(damageTreeWithPrediction.Position, true);
                            timberChain.Position     = predictedPosition;
                            timberChain.ChakramCombo = distanceToEnemy > 600 && usableChakram != null;
                            whirlingDeath.Combo      = (distanceToEnemy < 400 || distanceToEnemy > 600) &&
                                                       whirlingDeath.CanBeCasted();

                            var sleep = timberChain.GetSleepTime
                                        + (float)hero.GetTurnTime(damageTreeWithPrediction.Position) * 1000;

                            if (whirlingDeath.Combo)
                            {
                                whirlingDeath.SetComboDelay(
                                    sleep - ping
                                    + heroPosition.Distance2D(damageTreeWithPrediction) / timberChain.Speed * 1000
                                    + distanceToEnemy / timberChain.Speed * 1000);
                            }

                            sleeper.Sleep(sleep + ping, this);
                            return;
                        }
                    }
                    else if (timberChain.Level >= 4 && hero.Mana > 500)
                    {
                        if (target.IsVsisible || distanceToEnemy > 400)
                        {
                            var chaseTree = treeFactory.GetChaseTree(hero, target, timberChain, 400, 600);

                            if (chaseTree != null)
                            {
                                timberChain.UseAbility(chaseTree.Position);

                                sleeper.Sleep(
                                    timberChain.GetSleepTime + (float)hero.GetTurnTime(chaseTree.Position) * 1000
                                    + ping,
                                    this);
                                return;
                            }
                        }
                    }
                }

                if (usableChakram != null &&
                    (distanceToEnemy < 600 || target.FindAngle(heroPosition) <= 0.6 || timberChain.ChakramCombo) &&
                    (!whirlingDeath.Combo || !whirlingDeath.ComboDelayPassed)
                    /*&& (TimberPrediction.StraightTime(target.Hero) > 500 || distanceToEnemy < 300)*/)
                {
                    var predictedPosition = TimberPrediction.PredictedXYZ(
                        hero,
                        target,
                        usableChakram.GetSleepTime + ping
                        + target.GetDistance(heroPosition) / usableChakram.Speed * 1000
                        + usableChakram.Radius / 2 / target.Hero.MovementSpeed * 1000);

                    usableChakram.UseAbility(predictedPosition, target.Hero, hero);
                    timberChain.ChakramCombo = false;

                    treeFactory.SetUnavailableTrees(hero.Position, predictedPosition, usableChakram);

                    sleeper.Sleep(
                        usableChakram.GetSleepTime + (float)hero.GetTurnTime(predictedPosition) * 1000 + ping,
                        this);
                    return;
                }

                if (!sleeper.Sleeping(orbwalker))
                {
                    orbwalker.OrbwalkOn(target.Hero, target.GetPosition());
                }
            }
            else if (target.Locked)
            {
                if (cameraCentered)
                {
                    Game.ExecuteCommand("-dota_camera_center_on_hero");
                    cameraCentered = false;
                }

                if (timberChain.IsInPhase)
                {
                    timberChain.Stop(hero);
                }

                treeFactory.ClearUnavailableTrees(true);
                timberChain.ChakramCombo = false;
                whirlingDeath.Combo      = false;

                var phaseChakrams  = chakrams.Where(x => x.IsInPhase).ToList();
                var castedChakrams = chakrams.Where(x => x.Casted).ToList();

                if (phaseChakrams.Any())
                {
                    phaseChakrams.ForEach(x => x.Stop(hero));
                }
                else if (castedChakrams.Any())
                {
                    castedChakrams.ForEach(x => x.Return());
                }
                else
                {
                    target.Locked = false;
                }

                sleeper.Sleep(500, this);
            }

            treeFactory.ClearUnavailableTrees();
        }
Пример #7
0
        public void OnUpdate()
        {
            if (!Utils.SleepCheck("Timbersaw.Sleep"))
            {
                return;
            }

            if (Game.IsPaused || !hero.IsAlive || !hero.CanCast() || hero.IsChanneling() || !menuManager.IsEnabled)
            {
                return;
            }

            if (!aghsAdded && Utils.SleepCheck("Timbersaw.Aghanim"))
            {
                if (hero.AghanimState())
                {
                    chakrams.Add(chakram2);
                    aghsAdded = true;
                }
                Utils.Sleep(5000, "Timbersaw.Aghanim");
            }

            if (menuManager.EscapeEnabled)
            {
                var blink = hero.FindItem("item_blink", true);

                if (Utils.SleepCheck("Timbersaw.Blink") && blink != null && blink.CanBeCasted())
                {
                    var mouse     = Game.MousePosition;
                    var castRange = blink.GetCastRange();

                    var blinkPosition = hero.Distance2D(Game.MousePosition) > castRange
                                            ? (mouse - heroPosition) * castRange / mouse.Distance2D(hero) + heroPosition
                                            : Game.MousePosition;

                    blink.UseAbility(blinkPosition);
                    Utils.Sleep(1000, "Timbersaw.Blink");
                }
                else if (timberChain.CanBeCasted())
                {
                    var chaseTree = treeFactory.GetEscapeTree(hero, Game.MousePosition, timberChain.GetCastRange(), 800);

                    if (chaseTree != null)
                    {
                        timberChain.UseAbility(chaseTree.Position);
                        Utils.Sleep(
                            timberChain.GetSleepTime + chaseTree.Distance2D(hero) / timberChain.Speed * 1000 * 2
                            + Game.Ping,
                            "Timbersaw.Sleep");
                        return;
                    }
                }

                if (Utils.SleepCheck("Timbersaw.Move"))
                {
                    hero.Move(Game.MousePosition);
                    Utils.Sleep(100, "Timbersaw.Move");
                }
            }
            else if (menuManager.ChaseEnabled)
            {
                if (!target.IsValid())
                {
                    return;
                }

                if (!target.Locked)
                {
                    target.Locked = true;
                }

                if (!cameraCentered && menuManager.IsCenterCameraEnabled)
                {
                    Game.ExecuteCommand("+dota_camera_center_on_hero");
                    cameraCentered = true;
                }

                var distanceToEnemy = target.GetDistance(heroPosition);
                var targetPosition  = target.GetPosition();
                var ping            = Game.Ping;

                var phaseChakram = chakrams.FirstOrDefault(x => x.IsInPhase);

                if (phaseChakram != null)
                {
                    var predictedPosition = TimberPrediction.PredictedXYZ(
                        target,
                        distanceToEnemy / phaseChakram.Speed * 1000);

                    if (phaseChakram.Position.Distance2D(predictedPosition) > phaseChakram.Radius)
                    {
                        chakram.Stop(hero);
                        Utils.Sleep(ping + 100, "Timbersaw.Sleep");
                        return;
                    }
                }

                if (timberChain.IsInPhase && timberChain.CastedOnEnemy)
                {
                    var predictedPosition = TimberPrediction.PredictedXYZ(
                        target,
                        distanceToEnemy / timberChain.Speed * 1000);

                    if (timberChain.Position.Distance2D(predictedPosition) > timberChain.Radius)
                    {
                        timberChain.Stop(hero);
                        timberChain.ChakramCombo = false;
                        whirlingDeath.Combo      = false;
                        Utils.Sleep(ping + 100, "Timbersaw.Sleep");
                        return;
                    }
                }

                chakrams.FirstOrDefault(x => x.ShouldReturn(hero, target))?.Return();

                var blink    = hero.FindItem("item_blink", true);
                var shiva    = hero.FindItem("item_shivas_guard", true);
                var soulring = hero.FindItem("item_soul_ring");

                var usableChakram = chakrams.FirstOrDefault(x => x.CanBeCasted());

                if (Utils.SleepCheck("Timbersaw.Blink") && blink != null && blink.CanBeCasted() && distanceToEnemy > 400 &&
                    (target.GetTurnTime(heroPosition) > 0 || distanceToEnemy > 600) &&
                    (timberChain.Cooldown > 2 || distanceToEnemy > 800) &&
                    (whirlingDeath.CanBeCasted() || usableChakram != null) &&
                    hero.Modifiers.All(x => x.Name != timberChain.ModifierName) && !timberChain.IsSleeping)
                {
                    var castRange = blink.GetCastRange();

                    var sleep = ping + 300d;

                    if (distanceToEnemy <= castRange)
                    {
                        var positionNearTree = treeFactory.GetBlinkPosition(
                            target,
                            heroPosition,
                            castRange,
                            whirlingDeath.Radius,
                            whirlingDeath.CanBeCasted());

                        sleep += hero.GetTurnTime(positionNearTree);
                        blink.UseAbility(positionNearTree);
                    }
                    else
                    {
                        var maxDistancePosition = (targetPosition - heroPosition) * castRange
                                                  / targetPosition.Distance2D(hero) + heroPosition;

                        sleep += hero.GetTurnTime(maxDistancePosition);
                        blink.UseAbility(maxDistancePosition);
                    }

                    Utils.Sleep(1000, "Timbersaw.Blink");
                    Utils.Sleep(sleep, "Timbersaw.Sleep");
                    return;
                }

                if (Utils.SleepCheck("Timbersaw.SoulRing") && soulring != null && soulring.CanBeCasted())
                {
                    soulring.UseAbility();
                    Utils.Sleep(1000, "Timbersaw.SoulRing");
                }

                if (Utils.SleepCheck("Timbersaw.Shiva") && shiva != null && shiva.CanBeCasted() && distanceToEnemy < 500)
                {
                    shiva.UseAbility();
                    Utils.Sleep(1000, "Timbersaw.Shiva");
                }

                if (whirlingDeath.CanBeCasted() &&
                    (distanceToEnemy <= whirlingDeath.Radius ||
                     (whirlingDeath.Combo && whirlingDeath.ComboDelayPassed)))
                {
                    whirlingDeath.UseAbility();
                    whirlingDeath.Combo      = false;
                    timberChain.ChakramCombo = false;
                }

                if (timberChain.CanBeCasted() && (usableChakram == null || distanceToEnemy > 300))
                {
                    var possibleDamageTree = treeFactory.GetDamageTree(
                        heroPosition,
                        targetPosition,
                        timberChain.GetCastRange(),
                        timberChain.Radius);

                    if (target.IsVsisible && possibleDamageTree != null)
                    {
                        var predictedPosition = TimberPrediction.PredictedXYZ(
                            target,
                            timberChain.CastPoint * 1000
                            + (distanceToEnemy + hero.Distance2D(possibleDamageTree.Position)) / timberChain.Speed
                            * 1000 + ping);

                        var damageTreeWithPrediction = treeFactory.GetDamageTree(
                            heroPosition,
                            predictedPosition,
                            timberChain.GetCastRange(),
                            timberChain.Radius);

                        if (damageTreeWithPrediction != null)
                        {
                            timberChain.UseAbility(damageTreeWithPrediction.Position, true);
                            timberChain.Position     = predictedPosition;
                            timberChain.ChakramCombo = distanceToEnemy > 600 && usableChakram != null;
                            whirlingDeath.Combo      = (distanceToEnemy < 400 || distanceToEnemy > 600) &&
                                                       whirlingDeath.CanBeCasted();

                            var sleep = timberChain.GetSleepTime
                                        + hero.GetTurnTime(damageTreeWithPrediction.Position) * 1000;

                            if (whirlingDeath.Combo)
                            {
                                whirlingDeath.SetComboDelay(
                                    sleep - ping
                                    + heroPosition.Distance2D(damageTreeWithPrediction) / timberChain.Speed * 1000
                                    + distanceToEnemy / timberChain.Speed * 1000);
                            }

                            Utils.Sleep(sleep + ping, "Timbersaw.Sleep");
                            return;
                        }
                    }
                    else if (timberChain.Level >= 4)
                    {
                        if (target.IsVsisible || distanceToEnemy > 300)
                        {
                            var chaseTree = treeFactory.GetChaseTree(heroPosition, target, timberChain, 300, 500);

                            if (chaseTree != null)
                            {
                                timberChain.UseAbility(chaseTree.Position);
                                Utils.Sleep(
                                    timberChain.GetSleepTime + hero.GetTurnTime(chaseTree.Position) * 1000 + ping,
                                    "Timbersaw.Sleep");
                                return;
                            }
                        }
                    }
                }

                if (usableChakram != null &&
                    (distanceToEnemy < 600 || target.GetTurnTime(heroPosition) <= 0 || timberChain.ChakramCombo) &&
                    (!whirlingDeath.Combo || !whirlingDeath.ComboDelayPassed) &&
                    TimberPrediction.StraightTime(target.Hero) > 500)
                {
                    var predictedPosition = TimberPrediction.PredictedXYZ(
                        target,
                        usableChakram.GetSleepTime + ping
                        + target.GetDistance(heroPosition) / usableChakram.Speed * 1000
                        + usableChakram.Radius / 2 / target.Hero.MovementSpeed * 1000);

                    usableChakram.UseAbility(predictedPosition, target.Hero);

                    timberChain.ChakramCombo = false;

                    Utils.Sleep(
                        usableChakram.GetSleepTime + hero.GetTurnTime(predictedPosition) * 1000 + ping,
                        "Timbersaw.Sleep");
                    return;
                }

                orbwalker.OrbwalkOn(target.Hero, target.GetPosition());
            }
            else if (target.Locked)
            {
                if (cameraCentered)
                {
                    Game.ExecuteCommand("-dota_camera_center_on_hero");
                    cameraCentered = false;
                }

                var phaseChakrams  = chakrams.Where(x => x.IsInPhase).ToList();
                var castedChakrams = chakrams.Where(x => x.Casted).ToList();

                if (phaseChakrams.Any())
                {
                    phaseChakrams.ForEach(x => x.Stop(hero));
                }
                else if (castedChakrams.Any())
                {
                    castedChakrams.ForEach(x => x.Return());
                }
                else
                {
                    target.Locked = false;
                }

                Utils.Sleep(500, "Timbersaw.Sleep");
            }
        }