예제 #1
0
        protected void HandleMovement()
        {
            var playerModel = GameState.Instance.PlayerRpgState;

            if (!GameState.Instance.PlayerFlags.Contains(PlayerFlags.Frozen) && !GameState.Instance.PlayerFlags.Contains(PlayerFlags.TotallyFrozen))
            {
                //handle running
                float energyToRun = RpgValues.GetRunEnergyRate(playerModel);

                IsRunning = MappedInput.GetButton(DefaultControls.Sprint);

                if (RunWasBlocked && IsRunning)
                {
                    IsRunning = false;
                }
                else if (RunWasBlocked && !IsRunning)
                {
                    RunWasBlocked = false;
                }

                if (IsRunning && playerModel.Energy < energyToRun)
                {
                    IsRunning     = false;
                    RunWasBlocked = true;
                    QdmsMessageBus.Instance.PushBroadcast(new QdmsFlagMessage("RpgInsufficientEnergy"));
                }


                //TODO check against energy requirements

                //request an exit from ADS
                if (IsRunning && PlayerController.WeaponComponent != null)
                {
                    PlayerController.WeaponComponent.RequestADSExit();
                }

                //handle crouching
                if (MappedInput.GetButtonDown(DefaultControls.Crouch) && !IsRunning)
                {
                    IsCrouching     = !IsCrouching;
                    DidChangeCrouch = true;
                    SetCrouchState();
                }

                //uncrouch if we try to sprint
                if (IsRunning && IsCrouching)
                {
                    IsCrouching     = false;
                    DidChangeCrouch = true;
                    SetCrouchState();
                }

                if (IsGrounded)
                {
                    //normal x/y movement

                    var flatVelocity = new Vector3(Velocity.x, 0, Velocity.z);

                    Vector3 moveVector = Vector3.zero;

                    float maxAcceleration = IsCrouching ? MaxCrouchAcceleration : (IsRunning ? MaxSprintAcceleration : MaxWalkAcceleration);
                    if (Mathf.Abs(MappedInput.GetAxis(DefaultControls.MoveY)) > InputDeadzone)
                    {
                        moveVector += (transform.forward * MappedInput.GetAxis(DefaultControls.MoveY) * maxAcceleration * Time.deltaTime);
                        IsMoving    = true;
                    }

                    if (Mathf.Abs(MappedInput.GetAxis(DefaultControls.MoveX)) > InputDeadzone)
                    {
                        moveVector += (transform.right * MappedInput.GetAxis(DefaultControls.MoveX) * maxAcceleration * Time.deltaTime);
                        IsMoving    = true;
                    }

                    if (Mathf.Approximately(moveVector.magnitude, 0) && !IsOnSlope)
                    {
                        moveVector = -flatVelocity.normalized * Mathf.Min(MaxBrakeAcceleration * Time.deltaTime, flatVelocity.magnitude);
                    }

                    //clamp velocity to maxwalk/maxrun/etc
                    float maxSpeed = IsCrouching ? MaxCrouchSpeed * RpgValues.GetMoveSpeedMultiplier(playerModel) : (IsRunning ? MaxSprintSpeed * RpgValues.GetRunSpeedMultiplier(playerModel) : MaxWalkSpeed * RpgValues.GetMoveSpeedMultiplier(playerModel));
                    maxSpeed *= ConfigState.Instance.GetGameplayConfig().Difficulty.PlayerAgility;
                    var newFlatVelocity = new Vector3(Velocity.x, 0, Velocity.z) + new Vector3(moveVector.x, 0, moveVector.z);
                    if (newFlatVelocity.magnitude > maxSpeed)
                    {
                        newFlatVelocity = newFlatVelocity.normalized * maxSpeed; //this actually doesn't make a ton of physical sense but it does seem to work
                    }

                    Velocity = new Vector3(newFlatVelocity.x, Velocity.y, newFlatVelocity.z);

                    if (IsRunning)
                    {
                        playerModel.Energy -= energyToRun;
                    }
                }
                else
                {
                    //air move: component wise, clamped

                    //awkward bullshit to go from world to player space
                    Vector3 refVelocity    = Quaternion.AngleAxis(-transform.eulerAngles.y, Vector3.up) * Velocity;
                    Vector3 newAddVelocity = Vector3.zero;

                    float multiplier = ConfigState.Instance.GetGameplayConfig().Difficulty.PlayerAgility;
                    multiplier *= RpgValues.GetAirMoveMultiplier(playerModel);

                    float maxSpeedScaled = MaxAirSpeed * multiplier;

                    float moveZ = MappedInput.GetAxis(DefaultControls.MoveY) * MaxAirAcceleration * multiplier * Time.deltaTime;
                    if (Mathf.Abs(refVelocity.z) < maxSpeedScaled || Mathf.Sign(moveZ) != Mathf.Sign(refVelocity.z))
                    {
                        newAddVelocity += new Vector3(0, 0, moveZ);
                    }

                    float moveX = MappedInput.GetAxis(DefaultControls.MoveX) * MaxAirAcceleration * multiplier * Time.deltaTime;
                    if (Mathf.Abs(refVelocity.x) < maxSpeedScaled || Mathf.Sign(moveX) != Mathf.Sign(refVelocity.x))
                    {
                        newAddVelocity += new Vector3(moveX, 0, 0);
                    }

                    Velocity += Quaternion.AngleAxis(transform.eulerAngles.y, Vector3.up) * newAddVelocity;
                }

                if (IsGrounded && (AllowSlopeJumping || !IsOnSlope))
                {
                    //jumping
                    if (MappedInput.GetButtonDown(DefaultControls.Jump))
                    {
                        var   jumpVelocity  = JumpInstantaneousVelocity * RpgValues.GetJumpVelocityMultiplier(playerModel) * ConfigState.Instance.GetGameplayConfig().Difficulty.PlayerAgility;
                        float jumpEnergyUse = RpgValues.GetJumpEnergyUse(playerModel);

                        if (playerModel.Energy >= jumpEnergyUse)
                        {
                            playerModel.Energy -= jumpEnergyUse;
                            bool wasCrouched = IsCrouching;

                            //uncrouch if we were crouched
                            if (wasCrouched)
                            {
                                IsCrouching     = false;
                                DidChangeCrouch = true;
                                SetCrouchState();
                                jumpVelocity += JumpCrouchBoostVelocity;
                            }

                            Velocity += Quaternion.AngleAxis(transform.eulerAngles.y, Vector3.up) * jumpVelocity;
                            CharController.Move(Quaternion.AngleAxis(transform.eulerAngles.y, Vector3.up) * JumpInstantaneousDisplacement);
                            JumpSound.Ref()?.Play();
                            DidJump = true;
                        }
                        else
                        {
                            //failed to jump
                            QdmsMessageBus.Instance.PushBroadcast(new QdmsFlagMessage("RpgInsufficientEnergy"));
                        }
                    }
                }
            }

            //energy recovery
            if (!IsRunning && IsGrounded && !DidJump)
            {
                float energyGain = (IsMoving ? RpgValues.GetMovingEnergyRecoveryRate(playerModel) : RpgValues.GetIdleEnergyRecoveryRate(playerModel)) * Time.deltaTime;
                playerModel.Energy = Mathf.Min(playerModel.DerivedStats.MaxEnergy, playerModel.Energy + energyGain);
            }
        }