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);
        }
예제 #2
0
        private void Update()
        {
            var targetTransform = TargetOverride == null ? transform.parent : TargetOverride.transform;

            if (targetTransform == null)
            {
                return;
            }

            if (_cachedTransform != targetTransform)
            {
                _cachedTransform    = targetTransform;
                _cachedAIController = _cachedTransform.GetComponent <AIController>();
                _cachedMotor        = _cachedTransform.GetComponent <CharacterMotor>();
            }

            if (_cachedAIController == null)
            {
                return;
            }

            var character = Characters.Get(_cachedAIController.gameObject);

            if (character.Motor.IsAlive && !_cachedAIController.IsAlerted && (DisplayWhenAway || character.IsAnyInSight(0)))
            {
                _alpha += Time.deltaTime * FadeSpeed;
            }
            else
            {
                _alpha -= Time.deltaTime * FadeSpeed;
            }

            if (_cachedMotor != null)
            {
                var target = _cachedMotor.HeadLookTarget;
                target.y = transform.position.y;

                transform.LookAt(target);
            }

            _alpha = Mathf.Clamp01(_alpha);
            _mesh.Clear();

            var vertexCount = Detail * 3;
            var indexCount  = Detail * 3;

            if (_positions == null || _positions.Length != vertexCount)
            {
                _positions = new Vector3[vertexCount];
            }

            if (_colors == null || _colors.Length != vertexCount)
            {
                _colors = new Color[vertexCount];
            }

            if (_uv == null || _uv.Length != vertexCount)
            {
                _uv = new Vector2[vertexCount];
            }

            var wasEdited = false;

            if (_alpha >= 1f / 255f)
            {
                wasEdited = true;

                var fov      = _cachedAIController.View.FieldOfView * _alpha;
                var distance = _cachedAIController.View.SightDistance;

                for (int i = 0; i < Detail; i++)
                {
                    float a0 = fov * ((float)i / (float)Detail - 0.5f) + 90;
                    float a1 = fov * ((float)(i + 1) / (float)Detail - 0.5f) + 90;

                    _positions[i * 3 + 0] = Vector3.zero;
                    _positions[i * 3 + 1] = new Vector3(Mathf.Cos(a1 * Mathf.Deg2Rad), 0, Mathf.Sin(a1 * Mathf.Deg2Rad)) * distance;
                    _positions[i * 3 + 2] = new Vector3(Mathf.Cos(a0 * Mathf.Deg2Rad), 0, Mathf.Sin(a0 * Mathf.Deg2Rad)) * distance;
                }

                for (int i = 0; i < _colors.Length; i++)
                {
                    _colors[i] = new Color(1, 1, 1, _alpha);
                }

                for (int i = 0; i < _uv.Length; i++)
                {
                    _uv[i] = new Vector2((_positions[i].x / distance) * 0.5f + 0.5f, (_positions[i].z / distance) * 0.5f + 0.5f);
                }

                if (_indices == null || _indices.Length != indexCount)
                {
                    _indices = new int[indexCount];

                    for (int i = 0; i < _indices.Length; i++)
                    {
                        _indices[i] = i;
                    }
                }
            }

            if (wasEdited || !_hasSetAtLeastOnce)
            {
                _hasSetAtLeastOnce = true;

                _mesh.vertices  = _positions;
                _mesh.colors    = _colors;
                _mesh.uv        = _uv;
                _mesh.triangles = _indices;
            }
        }
예제 #3
0
        private void Update()
        {
            if (!_isAssaulting)
            {
                return;
            }

            _wait += Time.deltaTime;

            if (_wait >= MaxDuration)
            {
                ToStopAssault();
            }
            else if (isMelee)
            {
                if (_motor.IsPerformingMelee)
                {
                    if (_brain.Threat != null)
                    {
                        var vector   = _brain.Threat.transform.position - transform.position;
                        var distance = vector.magnitude;

                        if (distance <= MaxMeleeDistance)
                        {
                            _motor.InputCombo(_brain.Threat.transform.position);
                        }
                    }

                    _postHitTime = PostHitFreezeDuration;
                    _blockWait   = 0;
                }
                else
                {
                    if (_wasEverInMeleeRange)
                    {
                        _blockWait += Time.deltaTime;
                    }

                    if (_isGoingToHit)
                    {
                        _preHitTime -= Time.deltaTime;
                    }
                    else if (_postHitTime > 0)
                    {
                        _postHitTime -= Time.deltaTime;
                    }

                    var isInRange = false;

                    const float minMovementDuration = 0.2f;

                    if (_brain.Threat != null)
                    {
                        var vector    = _brain.Threat.transform.position - transform.position;
                        var distance  = vector.magnitude;
                        var direction = vector.normalized;

                        const float MaxThreshold = 1;

                        var targetIsLow = _brain.Threat.Motor == null ? false : _brain.Threat.Motor.IsLow;

                        if (_wasInMeleeRange && distance <= MaxMeleeDistance + MaxThreshold)
                        {
                            if (_isGoingToHit)
                            {
                                if (_preHitTime <= float.Epsilon)
                                {
                                    if (targetIsLow && distance < MinMeleeDistance && _motor.IsFreeToMove(-direction))
                                    {
                                        if (distance < MinMeleeDistance * 0.35f)
                                        {
                                            _motor.InputMovement(new CharacterMovement(-direction, 1, minMovementDuration));
                                        }
                                        else
                                        {
                                            _motor.InputMovement(new CharacterMovement(-direction, 0.5f, minMovementDuration));
                                        }
                                    }
                                    else
                                    {
                                        _isGoingToHit = false;
                                        _motor.InputMelee(_brain.Threat.transform.position);
                                    }
                                }
                            }
                            else if (_postHitTime <= float.Epsilon)
                            {
                                _motor.InputBlock();
                            }
                        }

                        if (distance <= MaxMeleeDistance)
                        {
                            if (targetIsLow)
                            {
                                _motor.InputVerticalMeleeAngle(30);
                            }
                            else
                            {
                                _motor.InputVerticalMeleeAngle(0);
                            }

                            isInRange = true;
                            SendMessage("ToTurnAt", _brain.Threat.transform.position);

                            if (distance < MinMeleeDistance && _motor.IsFreeToMove(-direction))
                            {
                                if (distance < MinMeleeDistance * 0.35f)
                                {
                                    _motor.InputMovement(new CharacterMovement(-direction, 1, minMovementDuration));
                                }
                                else
                                {
                                    _motor.InputMovement(new CharacterMovement(-direction, 0.5f, minMovementDuration));
                                }
                            }
                            else
                            {
                                var wasGoingToHit = _isGoingToHit;

                                if (_blockWait > MaxBlockDuration)
                                {
                                    _isGoingToHit = true;
                                }
                                else if (_blockWait > MinBlockDuration)
                                {
                                    var other = Characters.Get(_brain.Threat.gameObject);

                                    if (other.Motor == null || !other.Motor.IsPerformingMelee)
                                    {
                                        _isGoingToHit = true;
                                    }
                                }

                                if (_isGoingToHit && !wasGoingToHit)
                                {
                                    _preHitTime = PreHitFreezeDuration;
                                }
                            }

                            SendMessage("ToStopMoving");
                        }
                        else if (_wasInMeleeRange && distance < MaxMeleeDistance + MaxThreshold)
                        {
                            if (_postHitTime < 0)
                            {
                                _motor.InputBlock();
                            }

                            isInRange = true;
                            _motor.InputMovement(new CharacterMovement(vector / distance, 0.5f, minMovementDuration));
                        }
                        else if (distance > MaxMeleeDistance * 10)
                        {
                            _wasEverInMeleeRange = false;
                        }
                    }

                    if (isInRange)
                    {
                        _wasEverInMeleeRange = true;
                        _wasInMeleeRange     = true;
                    }
                    else
                    {
                        _motor.InputVerticalMeleeAngle(0);

                        if (_wasInMeleeRange)
                        {
                            _isGoingToHit    = false;
                            _blockWait       = 0;
                            _wasInMeleeRange = false;
                            _targetPosition  = _threatPosition;
                            runTo(_targetPosition);
                        }
                    }
                }
            }
            else
            {
                if (Vector3.Distance(transform.position, _targetPosition) <= NonMeleeDistance)
                {
                    ToStopAssault();
                }
            }
        }