public override EvadeResult Evade(Unit9 ally, IObstacle obstacle) { var result = new EvadeResult { Ally = ally.DisplayName, EnemyAbility = obstacle.EvadableAbility.Ability.DisplayName, IsModifier = obstacle.IsModifierObstacle, Mode = EvadeMode.Dodge, ObstacleId = obstacle.Id }; if (!obstacle.CanBeDodged || ally.IsCourier) { result.State = EvadeResult.EvadeState.Ignore; return(result); } if (this.pathfinderMode == Pathfinder.EvadeMode.None) { result.State = EvadeResult.EvadeState.Ignore; return(result); } if ((this.pathfinderMode == Pathfinder.EvadeMode.Disables || ally.IsCharging) && !obstacle.EvadableAbility.Ability.IsDisable()) { result.State = EvadeResult.EvadeState.Ignore; return(result); } if (!ally.CanUseAbilities) { result.State = EvadeResult.EvadeState.Ignore; return(result); } if (ally.IsInvulnerable || (!obstacle.EvadableAbility.Ability.CanHitSpellImmuneEnemy && ally.IsMagicImmune)) { result.State = EvadeResult.EvadeState.Successful; return(result); } if (!ally.CanMove(false)) { result.State = EvadeResult.EvadeState.Failed; return(result); } if (!ally.IsControllable || this.ActionManager.IsInputBlocked(ally)) { result.State = EvadeResult.EvadeState.Failed; return(result); } var remainingTime = obstacle.GetEvadeTime(ally, true) - (Game.Ping / 2000f); if (remainingTime <= 0) { result.State = EvadeResult.EvadeState.Failed; return(result); } var movingIntoObstacle = !obstacle.IsIntersecting(ally, false); var path = movingIntoObstacle ? this.pathfinder.GetPathFromObstacle(ally, ally.Speed, ally.InFront(100), 69, out var success) : this.pathfinder.GetPathFromObstacle(ally, ally.Speed, ally.Position, 69, out success); if (!success) { result.State = EvadeResult.EvadeState.Failed; return(result); } var ignoreTime = obstacle.EvadableAbility.IgnoreRemainingTime(obstacle, null); var movePosition = path.Last(); var requiredTime = this.GetRequiredTime(ally, movePosition, remainingTime, out var speedBuffAbility) - 0.15f; if (obstacle is AreaOfEffectObstacle) { remainingTime -= 0.15f; } if (!ignoreTime) { if (requiredTime > remainingTime) { result.State = EvadeResult.EvadeState.Failed; return(result); } if (requiredTime + 0.15 < remainingTime) { if (EvadeModeManager.MoveCamera && !Hud.IsPositionOnScreen(movePosition)) { Hud.CameraPosition = movePosition; } result.State = EvadeResult.EvadeState.TooEarly; return(result); } } if (ally.IsRuptured && ally.Distance(movePosition) > 300) { result.State = EvadeResult.EvadeState.Failed; return(result); } if (!this.ChannelCanceled(ally, obstacle, remainingTime, null)) { result.State = EvadeResult.EvadeState.Failed; return(result); } if (!this.PhaseCanceled(ally, obstacle, null)) { result.State = EvadeResult.EvadeState.Failed; return(result); } if (speedBuffAbility != null) { speedBuffAbility.Use(ally, null, null); result.AllyAbility = speedBuffAbility.Ability.DisplayName; } if (EvadeModeManager.MoveCamera && !Hud.IsPositionOnScreen(movePosition)) { Hud.CameraPosition = movePosition; } ally.BaseUnit.Move(movePosition, false, true); this.ActionManager.BlockInput(ally, obstacle, requiredTime + 0.2f); this.ActionManager.IgnoreObstacle(ally, obstacle, requiredTime + 0.5f); result.State = EvadeResult.EvadeState.Successful; return(result); }