private void Update()
        {
            if (_situation.IsAlerted)
            {
                if (!_hasAddedToAlertedControllers)
                {
                    _hasAddedToAlertedControllers = true;
                    _alertedControllers.Add(this);
                }
            }
            else if (_hasAddedToAlertedControllers)
            {
                _alertedControllers.Remove(this);
            }

            _stateTime += Time.deltaTime;

            _agent.updatePosition = false;
            _agent.updateRotation = false;
            _agent.updateUpAxis   = false;
            _agent.autoRepath     = true;
            _agent.autoBraking    = false;

            if (!_motor.IsAlive)
            {
                _situation.TargetCover = null;
            }

            if (_lastTargetCover != _situation.TargetCover)
            {
                if (_lastTargetCover != null)
                {
                    _lastTargetCover.UnregisterUser(_actor);
                }

                _lastTargetCover = _situation.TargetCover;

                if (_lastTargetCover != null)
                {
                    _lastTargetCover.RegisterUser(_actor);
                }
            }

            if (_isWaitingForPath && !_agent.pathPending)
            {
                _pathLength       = _agent.path.GetCornersNonAlloc(_path);
                _currentPathIndex = 0;
                _isWaitingForPath = false;
            }

            if (!_motor.IsAlive)
            {
                _state         = AIState.none;
                _agent.enabled = false;
                return;
            }
            else
            {
                _agent.enabled = true;
            }

            if (_motor.PotentialCover != null)
            {
                _motor.InputTakeCover();
            }

            if (_situation.IsAlerted)
            {
                if (!_motor.IsInCover)
                {
                    _motor.InputAim();
                }

                // Make the AI pick up a weapon.
                if (Fighting.WeaponToUse <= 0)
                {
                    _motor.InputWeapon(0);
                }
                else if (Fighting.WeaponToUse - 1 < _motor.Weapons.Length)
                {
                    _motor.InputWeapon(Fighting.WeaponToUse);
                }
                else
                {
                    _motor.InputWeapon(_motor.Weapons.Length);
                }

                _situation.IsAllowedToBeAggressive = true;

                ///
                /// POTENTIALLY FORGET ABOUT THE ENEMY. CHECK IF CAN BE AGGRESSIVE.
                ///
                if (_situation.Threat != null)
                {
                    if (_situation.Threat.IsAlive)
                    {
                        if (!_situation.CanSeeTheThreat && _situation.NoThreatTimer > View.EnemySustainTime)
                        {
                            _situation.RemoveEnemyState();
                        }
                        else
                        {
                            if (_registeredGroup != null)
                            {
                                _registeredGroup.MarkAsPotentialAggressive(this);
                                _situation.IsAllowedToBeAggressive = _registeredGroup.IsAggressive(this);
                            }
                        }
                    }
                    else
                    {
                        _situation.RemoveEnemyState();
                    }
                }

                ///
                /// AIM AND FIRE
                ///
                if (_situation.Threat != null && (_situation.CanSeeTheThreat || _situation.NoThreatTimer < View.SightSustainTime))
                {
                    // Process grenade throwing
                    if (_situation.ThrownGrenadeCount < Grenades.GrenadeCount)
                    {
                        var doThrow = false;

                        if (_situation.IsAllowedToBeAggressive)
                        {
                            if (_hasThrowFirstGrenade)
                            {
                                if (_grenadeTimer < Grenades.Interval)
                                {
                                    _grenadeTimer += Time.deltaTime;
                                }
                                else
                                {
                                    doThrow = true;
                                }
                            }
                            else
                            {
                                if (_grenadeTimer < Grenades.FirstGrenadeDelay)
                                {
                                    _grenadeTimer += Time.deltaTime;
                                }
                                else
                                {
                                    doThrow = true;
                                }
                            }
                        }

                        if (doThrow && _motor.PotentialGrenade != null)
                        {
                            if (_grenadeCheckTimer <= float.Epsilon)
                            {
                                GrenadeDescription desc;
                                desc.Gravity    = _motor.Grenade.Gravity;
                                desc.Duration   = _motor.PotentialGrenade.Timer;
                                desc.Bounciness = _motor.PotentialGrenade.Bounciness;

                                var length = GrenadePath.Calculate(GrenadePath.Origin(_motor, Util.AngleOfVector(_situation.ThreatGroundPosition - transform.position)),
                                                                   _situation.ThreatGroundPosition,
                                                                   _motor.Grenade.MaxVelocity,
                                                                   desc,
                                                                   _grenadePath,
                                                                   _motor.Grenade.Step);

                                if (Vector3.Distance(_grenadePath[length - 1], _situation.ThreatGroundPosition) > Grenades.MaxRadius ||
                                    Vector3.Distance(_grenadePath[length - 1], _situation.CurrentPosition) < Grenades.AvoidDistance)
                                {
                                    _grenadeCheckTimer = Grenades.CheckInterval;
                                }
                                else
                                {
                                    _motor.InputThrowGrenade(_grenadePath, length, _motor.Grenade.Step);
                                    _situation.ThrownGrenadeCount++;

                                    _grenadeTimer         = 0;
                                    _hasThrowFirstGrenade = true;
                                }
                            }
                            else
                            {
                                _grenadeCheckTimer -= Time.deltaTime;
                            }
                        }
                        else
                        {
                            _grenadeCheckTimer = 0;
                        }
                    }

                    // Position in world space that is best fit to aim at.
                    var perfectTarget = _situation.ThreatGroundPosition + (_situation.ThreatTopPosition - _situation.ThreatGroundPosition) * 0.7f;

                    if (_situation.IsThreatInCover)
                    {
                        var dot = Vector3.Dot(_situation.ThreatCoverForward, (_situation.ThreatGroundPosition - transform.position).normalized);

                        if (dot < -0.1f)
                        {
                            perfectTarget = _situation.ThreatStandingTopPosition;
                        }
                    }

                    // Make the AI look at the target.
                    {
                        var vector = perfectTarget - _motor.transform.position;
                        vector.y = 0;

                        if (vector.magnitude < 2)
                        {
                            _motor.SetLookTarget(perfectTarget + vector * 2);
                        }
                        else
                        {
                            _motor.SetLookTarget(perfectTarget);
                        }

                        _motor.SetBodyLookTarget(perfectTarget);
                    }

                    // Aim the gun at the inprecise target.
                    var targetRadius = Fighting.TargetRadius.Get(Vector3.Distance(_situation.ThreatGroundPosition, transform.position));
                    _motor.SetFireTarget(perfectTarget + new Vector3(UnityEngine.Random.Range(-1, 1) * targetRadius,
                                                                     UnityEngine.Random.Range(-1, 1) * targetRadius,
                                                                     UnityEngine.Random.Range(-1, 1) * targetRadius));

                    // We want AI too look at the corner when standing near it.
                    if (_motor.IsInTallCover)
                    {
                        if (_situation.TargetDirection < 0)
                        {
                            _motor.InputStandLeft();
                        }
                        else if (_situation.TargetDirection > 0)
                        {
                            _motor.InputStandRight();
                        }
                    }

                    // Fire
                    {
                        var isAllowedToFire = _situation.IsAllowedToBeAggressive;

                        if (Behaviour.OnlyFireWhenSeen || !_situation.IsAllowedToBeAggressive)
                        {
                            var up   = Camera.main.WorldToViewportPoint(transform.position);
                            var down = Camera.main.WorldToViewportPoint(transform.position + Vector3.up * 2);

                            if ((up.x < 0 ||
                                 up.y < 0 ||
                                 up.x > 1 ||
                                 up.y > 1 ||
                                 up.z < 0) &&
                                (down.x < 0 ||
                                 down.y < 0 ||
                                 down.x > 1 ||
                                 down.y > 1 ||
                                 down.z < 0))
                            {
                                isAllowedToFire = false;
                            }
                            else
                            {
                                isAllowedToFire = true;
                            }
                        }

                        if (isAllowedToFire)
                        {
                            var burst  = Behaviour.IsFightingUsingCovers ? CoveredFightingBursts : CoveredApproachBursts;
                            var isDumb = _state == AIState.fireInCover &&
                                         (_stateTime <= burst.IntroDuration || _stateTime >= burst.IntroDuration + burst.Duration);

                            var isWalking = _state != AIState.takeCover && _state != AIState.approach && _state != AIState.retreat;

                            // Check if can fire right now.
                            if (Behaviour.CanFire &&
                                (!isWalking || _walkingBurstWait < WalkingBursts.Duration) &&
                                (!_situation.IsTargetCoverGood ||
                                 (_state != AIState.hideInCover &&
                                  (_state != AIState.takeCover || _motor.Cover == null))))
                            {
                                var aimPoint = transform.position;

                                if (_motor.IsInTallCover && _situation.IsTargetCoverGood)
                                {
                                    if (_situation.TargetDirection < 0)
                                    {
                                        aimPoint = _motor.Cover.LeftCorner(transform.position.y, _motor.CoverSettings.CornerOffset.x);
                                    }
                                    else
                                    {
                                        aimPoint = _motor.Cover.RightCorner(transform.position.y, _motor.CoverSettings.CornerOffset.x);
                                    }
                                }

                                // See if the motor can hit the standing enemy after potentially peeking.
                                if (AIUtil.IsInSight(this, aimPoint, _situation.ThreatStandingTopPosition))
                                {
                                    if (_state == AIState.fireInCover)
                                    {
                                        _motor.InputAim();
                                    }

                                    if (!isDumb)
                                    {
                                        _motor.InputFire();
                                    }
                                }
                            }
                        }

                        _lookPointTimer = 0;
                    }
                }
                else
                {
                    _motor.SetFireTarget(_situation.ThreatGroundPosition);
                    _motor.SetLookTarget(_situation.ThreatGroundPosition);
                    _motor.SetBodyLookTarget(_situation.ThreatGroundPosition);
                    lookAround(_situation.ThreatGroundPosition - _motor.transform.position);
                }
            }
            else
            {
                _motor.InputWeapon(0);

                if (_state == AIState.patrol || _state == AIState.patrolPause)
                {
                    Vector3 forward;

                    if (Waypoints.Length > 1)
                    {
                        var next = Waypoints[_situation.PatrolPoint];

                        forward = next.Position - transform.position;

                        if (forward.magnitude < 0.5f)
                        {
                            var previous = _situation.PatrolPoint == 0 ? Waypoints[Waypoints.Length - 1] : Waypoints[_situation.PatrolPoint - 1];
                            var line     = next.Position - previous.Position;

                            if (Vector2.Dot(line, forward) > 0)
                            {
                                forward = line;
                            }
                        }
                    }
                    else
                    {
                        forward = transform.forward;
                    }

                    lookAround(forward);
                }
                else
                {
                    _lookPointTimer = 0;
                }
            }

            var positionToMoveTo = transform.position;

            ///
            /// STATE MANAGEMENT
            ///
            {
                var updateSituationInDetail = false;

                {
                    // Update the update delay timer.
                    _updateTimer -= Time.deltaTime;

                    if (_updateTimer < 0)
                    {
                        _updateTimer            = Fighting.ReactionTime;
                        updateSituationInDetail = true;
                    }
                }

                // Update standing burst timer.
                {
                    _walkingBurstWait += Time.deltaTime;

                    if (_walkingBurstWait > WalkingBursts.Duration + WalkingBursts.Wait)
                    {
                        _walkingBurstWait = 0;
                    }
                }

                {
                    _situation.Update(this, _previousSituation, updateSituationInDetail);

                    if (!isStateStillValid(_state, _stateTime, _situation, _situation))
                    {
                        updateSituation(calcState(_situation, _state, _stateTime));
                    }
                }
            }

            ///
            /// WALK
            ///
            if (!_motor.IsInCornerAimState)
            {
                if (_state == AIState.takeCover ||
                    _state == AIState.approach ||
                    _state == AIState.investigate ||
                    _state == AIState.retreat ||
                    _state == AIState.patrol ||
                    _state == AIState.avoidGrenade)
                {
                    var toTarget = _situation.TargetPosition - transform.position;

                    // If patrolling, set the body to rotate towards the target.
                    if (_state == AIState.patrol)
                    {
                        if (toTarget.magnitude > 0.1f)
                        {
                            var normalized = toTarget.normalized;
                            var position   = transform.position + normalized * 4;
                            var dot        = Vector3.Dot(toTarget.normalized, _motor.transform.forward);

                            if (Waypoints[_situation.PatrolPoint].Run)
                            {
                                _motor.SetBodyLookTarget(position, 8);
                            }
                            else
                            {
                                if (dot > 0)
                                {
                                    _motor.SetBodyLookTarget(position, 1.6f);
                                }
                                else if (dot > -0.5f)
                                {
                                    _motor.SetBodyLookTarget(position, 2.5f);
                                }
                                else
                                {
                                    _motor.SetBodyLookTarget(position, 4f);
                                }
                            }
                        }
                    }

                    // Move the last meter without using the agent.
                    if (toTarget.magnitude > 1.0f)
                    {
                        var vectorToAgent   = _agent.nextPosition - transform.position;
                        var distanceToAgent = vectorToAgent.magnitude;

                        if (distanceToAgent > float.Epsilon)
                        {
                            vectorToAgent /= distanceToAgent;
                        }

                        // If agent moved too far, reset it.
                        if (distanceToAgent > 1f)
                        {
                            updateAgent(_situation.TargetPosition);
                        }

                        float walkSpeed;

                        if (_state == AIState.patrol && !Patrol.IsAlwaysRunning && (Waypoints.Length == 0 || !Waypoints[_situation.PatrolPoint].Run))
                        {
                            walkSpeed = 0.5f;
                        }
                        else
                        {
                            walkSpeed = 1.0f;
                        }

                        var point = _currentPathIndex + 1 < _pathLength ? _path[_currentPathIndex + 1] : _situation.TargetPosition;

                        var vectorToPoint   = point - transform.position;
                        var distanceToPoint = vectorToPoint.magnitude;

                        if (distanceToPoint > float.Epsilon)
                        {
                            vectorToPoint /= distanceToPoint;
                        }

                        if (distanceToPoint < 0.1f && _currentPathIndex + 1 < _pathLength)
                        {
                            _currentPathIndex++;
                        }

                        _agent.speed = 0.1f;
                        _motor.InputMovement(new CharacterMovement(vectorToPoint, walkSpeed));
                    }
                    else
                    {
                        if (_state == AIState.takeCover)
                        {
                            _motor.InputImmediateCoverSearch();
                            _motor.InputTakeCover();
                        }

                        if (toTarget.magnitude > 0.05f)
                        {
                            _motor.InputMovement(new CharacterMovement(toTarget.normalized, 0.5f));
                        }
                        else
                        {
                            _motor.transform.position = _situation.TargetPosition;
                        }
                    }
                }
            }
        }
        public bool ManualUpdate()
        {
            if (_mode != Mode.Grenade)
            {
                destroyGrenadePreview();
            }

            checkLanded();

            switch (_mode)
            {
            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Default:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Aim));
                }

                if (isSprinting())
                {
                    return(transitionAndPerform(Mode.Sprint));
                }

                if (updateIsMelee())
                {
                    return(transitionAndPerform(Mode.Melee));
                }

                if (_motor.IsInCover)
                {
                    return(transitionAndPerform(Mode.Cover));
                }

                //// LOGIC //////////////////////

                checkArmLift();
                checkReload();
                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(1);
                checkCover();
                checkGrenade();
                checkCrouch();
                checkMelee();
            } break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Sprint:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Aim));
                }

                if (!isSprinting())
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                lowerArms();

                checkReload();
                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(2);
                checkCover();
                checkGrenade();
                checkCrouch();
            }
            break;

            case Mode.Cover:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Aim));
                }

                if (isSprinting())
                {
                    return(transitionAndPerform(Mode.Sprint));
                }

                if (updateIsMelee())
                {
                    return(transitionAndPerform(Mode.Melee));
                }

                if (!_motor.IsInCover)
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                lowerArms();

                checkMelee();
                checkReload();
                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(1);
                checkGrenade();
                checkCrouch();
            } break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Aim:
            {
                //// TRANSITIONS //////////////////////

                if (!updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                _noAimSustain = 0;

                if (AimWhenWalking && MovementInput.IsMoving)
                {
                    _aimSustain = AimSustain;
                }
                else
                {
                    _aimSustain -= Time.deltaTime;
                }

                checkZoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(1);
                checkCover();
                checkGrenade();
                checkCrouch();
                checkReload();
                checkMelee();

                if (CancelHurt)
                {
                    _motor.CancelAndPreventGetHit(0.3f);
                }

                liftArms();

                _motor.SetBodyTarget(BodyTargetInput);
                _motor.SetAimTarget(AimTargetInput);

                if (ImmediateTurns)
                {
                    _motor.InputPossibleImmediateTurn();
                }

                if (_motor.IsInCover)
                {
                    _motor.InputAimWhenLeavingCover();
                }

                _motor.InputAim();

                if (_motor.IsWeaponReady && FireInput)
                {
                    _aimSustain = AimSustain;

                    var gun = _motor.ActiveWeapon.Gun;

                    if (gun != null && gun.LoadedBulletsLeft <= 0)
                    {
                        _motor.InputReload();
                    }
                    else
                    {
                        _motor.InputFire();
                    }
                }

                if (_motor.IsWeaponScopeReady && ZoomInput)
                {
                    _aimSustain = AimSustain;

                    _motor.InputZoom();

                    if (_isScoping)
                    {
                        _motor.InputScope();
                    }
                }
            }
            break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Grenade:
            {
                if (!_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Default));
                }

                if (_motor.IsReadyToThrowGrenade && _motor.CurrentGrenade != null)
                {
                    GrenadeDescription desc;
                    desc.Gravity    = _motor.Grenade.Gravity;
                    desc.Duration   = _motor.PotentialGrenade.Timer;
                    desc.Bounciness = _motor.PotentialGrenade.Bounciness;

                    var verticalAngle = Mathf.Min(GrenadeVerticalAngleInput + ThrowAngleOffset, MaxThrowAngle);

                    var velocity = _motor.Grenade.MaxVelocity;

                    if (verticalAngle < 45)
                    {
                        velocity *= Mathf.Clamp01((verticalAngle + 15) / 45f);
                    }

                    _grenadePathLength = GrenadePath.Calculate(GrenadePath.Origin(_motor, GrenadeHorizontalAngleInput),
                                                               GrenadeHorizontalAngleInput,
                                                               verticalAngle,
                                                               velocity,
                                                               desc,
                                                               _grenadePath,
                                                               _motor.Grenade.Step);
                    _hasGrenadePath = true;

                    if (_explosionPreview == null && ExplosionPreview != null)
                    {
                        _explosionPreview = GameObject.Instantiate(ExplosionPreview);
                        _explosionPreview.transform.SetParent(null);
                        _explosionPreview.SetActive(true);
                    }

                    if (_explosionPreview != null)
                    {
                        _explosionPreview.transform.localScale = Vector3.one * _motor.PotentialGrenade.ExplosionRadius * 2;
                        _explosionPreview.transform.position   = _grenadePath[_grenadePathLength - 1];
                    }

                    if (_pathPreview == null && PathPreview != null)
                    {
                        _pathPreview = GameObject.Instantiate(PathPreview);
                        _pathPreview.transform.SetParent(null);
                        _pathPreview.SetActive(true);
                    }

                    if (_pathPreview != null)
                    {
                        _pathPreview.transform.position = _grenadePath[0];

                        var path = _pathPreview.GetComponent <PathPreview>();

                        if (path != null)
                        {
                            path.Points     = _grenadePath;
                            path.PointCount = _grenadePathLength;
                        }
                    }
                }
                else
                {
                    destroyGrenadePreview();
                }

                if (_hasGrenadePath && _wantsToThrowGrenade)
                {
                    if (ImmediateTurns)
                    {
                        _motor.InputPossibleImmediateTurn();
                    }

                    _motor.SetBodyTarget(BodyTargetInput);
                    _motor.SetAimTarget(BodyTargetInput);
                    _motor.InputThrowGrenade(_grenadePath, _grenadePathLength, _motor.Grenade.Step);
                }

                if (_wantsToCancelGrenade)
                {
                    _motor.InputCancelGrenade();
                }

                lowerArms();

                checkZoom();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(2);
                checkCover();
                checkCrouch();
            }
            break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Melee:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (isSprinting())
                {
                    return(transitionAndPerform(Mode.Sprint));
                }

                if (!updateIsMelee())
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(2);
                checkGrenade();
                checkCrouch();
                checkMelee();

                if (_meleeTarget != null)
                {
                    _motor.SetBodyTarget(_meleeTarget.transform.position);
                    _motor.SetAimTarget(_meleeTarget.transform.position + Vector3.up * 1.5f);
                    _motor.InputMeleeTarget(_meleeTarget.transform.position);

                    if (!MovementInput.IsMoving)
                    {
                        var vector   = _meleeTarget.transform.position - _motor.transform.position;
                        var distance = vector.magnitude;

                        if (distance < MinMeleeDistance)
                        {
                            var other = Characters.Get(_meleeTarget.gameObject);

                            if (other.Motor == null || !other.Motor.IsPerformingMelee)
                            {
                                const float minMovementDuration = 0.2f;

                                if (distance < MinMeleeDistance * 0.35f)
                                {
                                    _motor.InputMovement(new CharacterMovement(-vector / distance, 1, minMovementDuration));
                                }
                                else
                                {
                                    _motor.InputMovement(new CharacterMovement(-vector / distance, 0.5f, minMovementDuration));
                                }
                            }
                        }
                    }
                }
            }
            break;
            }

            // RESET

            _wantsToThrowGrenade  = false;
            _wantsToAim           = false;
            _wantsToHit           = false;
            _wantsToRoll          = false;
            _wantsToReload        = false;
            _wantsToUnequip       = false;
            _wantsToTakeGrenade   = false;
            _wantsToCancelGrenade = false;
            _wantsToCrouch        = false;
            _wantsToTakeCover     = false;
            _wantsToJump          = false;
            _wantsToClimbOrVault  = null;

            if (!_wantsToEquip.IsNull)
            {
                _wantsToEquip = new WeaponDescription();
            }

            // RETURN

            return(true);
        }
        private void Update()
        {
            if (_isActivating)
            {
                _activateTimer -= Time.deltaTime;

                if (_activateTimer < float.Epsilon)
                {
                    _isActivating = false;
                    _isActivated  = true;
                    GrenadeList.Register(this);
                    _timer = Timer;
                }
            }

            if (_isActivated)
            {
                if (_timer < float.Epsilon)
                {
                    explode();
                }
                else
                {
                    _timer -= Time.deltaTime;

                    if (_timer < Timer - PreviewTime)
                    {
                        if (_preview == null)
                        {
                            _preview = GameObject.Instantiate(ExplosionPreview);
                            _preview.transform.parent = null;
                            _preview.SetActive(true);
                        }

                        if (_preview != null)
                        {
                            _preview.transform.localScale = Vector3.one * ExplosionRadius * 2;
                            _preview.transform.position   = transform.position;
                        }
                    }
                    else if (_preview != null)
                    {
                        GameObject.Destroy(_preview);
                        _preview = null;
                    }
                }
            }

            if (_isFlying)
            {
                var position = transform.position;

                var previousOffset = _offset;
                _offset   = Vector3.Lerp(_offset, Vector3.zero, Time.deltaTime * 2);
                position += _offset - previousOffset;

                GrenadePath.Step(ref position, ref _velocity, Time.deltaTime, _gravity, Bounciness);

                transform.position = position;
            }
        }
        private void updateGrenadeAimAndPreview()
        {
            if ((HasAiming || _wasAiming) && IsAllowedToFire && _motor.IsAlive && _motor.IsReadyToThrowGrenade && _motor.CurrentGrenade != null)
            {
                GrenadeDescription desc;
                desc.Gravity    = _motor.Grenade.Gravity;
                desc.Duration   = _motor.PotentialGrenade.Timer;
                desc.Bounciness = _motor.PotentialGrenade.Bounciness;

                var angle    = Magnitude * 45f;
                var velocity = _motor.Grenade.MaxVelocity;

                if (angle < 45)
                {
                    velocity *= Mathf.Clamp01((angle + 15) / 45f);
                }

                _grenadePathLength = GrenadePath.Calculate(GrenadePath.Origin(_motor, _motor.LookAngle),
                                                           _motor.LookAngle,
                                                           angle,
                                                           velocity,
                                                           desc,
                                                           _grenadePath,
                                                           _motor.Grenade.Step);
                _hasGrenadePath = true;

                if (_explosionPreview == null && ExplosionPreview != null)
                {
                    _explosionPreview = GameObject.Instantiate(ExplosionPreview);
                    _explosionPreview.transform.parent = null;
                    _explosionPreview.SetActive(true);
                }

                if (_explosionPreview != null)
                {
                    _explosionPreview.transform.localScale = Vector3.one * _motor.PotentialGrenade.ExplosionRadius * 2;
                    _explosionPreview.transform.position   = _grenadePath[_grenadePathLength - 1];
                }

                if (_pathPreview == null && PathPreview != null)
                {
                    _pathPreview = GameObject.Instantiate(PathPreview);
                    _pathPreview.transform.parent = null;
                    _pathPreview.SetActive(true);
                }

                if (_pathPreview != null)
                {
                    _pathPreview.transform.position = _grenadePath[0];

                    var path = _pathPreview.GetComponent <PathPreview>();

                    if (path != null)
                    {
                        path.Points     = _grenadePath;
                        path.PointCount = _grenadePathLength;
                    }
                }
            }
            else
            {
                if (_explosionPreview != null)
                {
                    GameObject.Destroy(_explosionPreview);
                    _explosionPreview = null;
                }

                if (_pathPreview != null)
                {
                    GameObject.Destroy(_pathPreview);
                    _pathPreview = null;
                }

                _hasGrenadePath = false;
            }
        }