コード例 #1
0
        // TODO: Migrate this into seperate class accessible to climbingMotor and HangingMotor
        /// <summary>
        /// See if the player can pass a climbing skill check
        /// </summary>
        /// <returns>true if player passed climbing skill check</returns>
        public bool ClimbingSkillCheck(int basePercentSuccess)
        {
            player.TallySkill(DFCareer.Skills.Climbing, 1);

            if (overrideSkillCheck)
            {
                return(true);
            }

            int percentSuccess = FormulaHelper.CalculateClimbingChance(player, basePercentSuccess);

            if (Dice100.FailedRoll(percentSuccess))
            {
                // Don't allow skill check to break climbing while swimming
                // Water makes it easier to climb
                var playerPos     = controller.transform.position.y + (76 * MeshReader.GlobalScale) - 0.95f;
                var playerFootPos = playerPos - (controller.height / 2) - 1.20f; // to prevent player from failing to climb out of water
                var waterPos      = playerEnterExit.blockWaterLevel * -1 * MeshReader.GlobalScale;
                if (playerFootPos >= waterPos)                                   // prevent fail underwater
                {
                    return(false);
                }
            }
            return(true);
        }
コード例 #2
0
        private void ClimbMovement()
        {
            controller.Move(Vector3.up * Time.deltaTime);
            if (climbingContinueTimer <= (playerMotor.systemTimerUpdatesPerSecond * 15))
            {
                climbingContinueTimer += Time.deltaTime;
            }
            else
            {
                climbingContinueTimer = 0;
                Entity.PlayerEntity player = GameManager.Instance.PlayerEntity;
                player.TallySkill(DFCareer.Skills.Climbing, 1);
                int skill = player.Skills.GetLiveSkillValue(DFCareer.Skills.Climbing);
                if (player.Race == Entity.Races.Khajiit)
                {
                    skill += 30;
                }
                Mathf.Clamp(skill, 5, 95);

                if ((UnityEngine.Random.Range(1, 101) > 90) ||
                    (UnityEngine.Random.Range(1, 101) > skill))
                {
                    isClimbing = false;
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// See if the player can pass a climbing skill check
        /// </summary>
        /// <returns>true if player passed climbing skill check</returns>
        private bool SkillCheck(int basePercentSuccess)
        {
            player.TallySkill(DFCareer.Skills.Climbing, 1);

            if (overrideSkillCheck)
            {
                return(true);
            }

            int skill = player.Skills.GetLiveSkillValue(DFCareer.Skills.Climbing);
            int luck  = player.Stats.GetLiveStatValue(DFCareer.Stats.Luck);

            if (player.Race == Entity.Races.Khajiit)
            {
                skill += 30;
            }

            // Climbing effect states "target can climb twice as well" - doubling effective skill after racial applied
            if (player.IsEnhancedClimbing)
            {
                skill *= 2;
            }

            // Clamp skill range
            skill = Mathf.Clamp(skill, 5, 95);
            float luckFactor = Mathf.Lerp(0, 10, luck * 0.01f);

            // Skill Check
            float percentRolled = Mathf.Lerp(basePercentSuccess, 100, skill * .01f) + luckFactor;

            if (percentRolled < UnityEngine.Random.Range(1, 101)) // Failed Check?
            {
                // Don't allow skill check to break climbing while swimming
                // Water makes it easier to climb
                var playerPos     = controller.transform.position.y + (76 * MeshReader.GlobalScale) - 0.95f;
                var playerFootPos = playerPos - (controller.height / 2) - 1.20f; // to prevent player from failing to climb out of water
                var waterPos      = playerEnterExit.blockWaterLevel * -1 * MeshReader.GlobalScale;
                if (playerFootPos >= waterPos)                                   // prevent fail underwater
                {
                    return(false);
                }
            }
            return(true);
        }
コード例 #4
0
        public bool StealthCheck()
        {
            if (distanceToPlayer > 1024 * MeshReader.GlobalScale)
            {
                return(false);
            }

            uint gameMinutes = DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.ToClassicDaggerfallTime();

            if (gameMinutes == timeOfLastStealthCheck)
            {
                return(detectedPlayer);
            }

            PlayerMotor playerMotor = GameManager.Instance.PlayerMotor;

            if (playerMotor.IsMovingLessThanHalfSpeed)
            {
                if ((gameMinutes & 1) == 1)
                {
                    return(detectedPlayer);
                }
            }
            else if (hasEncounteredPlayer)
            {
                return(true);
            }

            Entity.PlayerEntity player = GameManager.Instance.PlayerEntity;
            if (player.TimeOfLastStealthCheck != gameMinutes)
            {
                player.TallySkill(DaggerfallConnect.DFCareer.Skills.Stealth, 1);
                player.TimeOfLastStealthCheck = gameMinutes;
            }
            timeOfLastStealthCheck = gameMinutes;

            int stealthRoll = 2 * ((int)(distanceToPlayer / MeshReader.GlobalScale) * player.Skills.GetLiveSkillValue(DaggerfallConnect.DFCareer.Skills.Stealth) >> 10);

            return(Random.Range(1, 101) > stealthRoll);
        }
コード例 #5
0
        /// <summary>
        /// See if the player can pass a climbing skill check
        /// </summary>
        /// <returns>true if player passed climbing skill check</returns>
        private bool SkillCheck(int basePercentSuccess)
        {
            player.TallySkill(DFCareer.Skills.Climbing, 1);
            int skill = player.Skills.GetLiveSkillValue(DFCareer.Skills.Climbing);

            if (player.Race == Entity.Races.Khajiit)
            {
                skill += 30;
            }

            // Climbing effect states "target can climb twice as well" - doubling effective skill after racial applied
            if (player.IsEnhancedClimbing)
            {
                skill *= 2;
            }

            // Clamp skill range
            skill = Mathf.Clamp(skill, 5, 95);

            // Skill Check
            float percentRolled = Mathf.Lerp(basePercentSuccess, 100, skill * .01f);

            if (percentRolled < UnityEngine.Random.Range(1, 101)) // Failed Check?
            {
                // Don't allow skill check to break climbing while swimming
                // This is another reason player can't climb out of water - any slip in climb will throw them back into swim mode
                // For now just pretend water is supporting player while they climb
                // It's not enough to check if they are swimming, need to check if their feet are above water. - MeteoricDragon
                var playerPos     = controller.transform.position.y + (76 * MeshReader.GlobalScale) - 0.95f;
                var playerFootPos = playerPos - (controller.height / 2) - 1.20f; // to prevent player from failing to climb out of water
                var waterPos      = playerEnterExit.blockWaterLevel * -1 * MeshReader.GlobalScale;
                if (playerFootPos >= waterPos)                                   // prevent fail underwater
                {
                    return(false);
                }
            }
            return(true);
        }
コード例 #6
0
        /// <summary>
        /// Check if should do rappel, and do rappel and attach to wall.
        /// </summary>
        public void RappelChecks()
        {
            if (rappelStage == RappelStage.Inactive)
            {
                measure = null;
            }
            else
            {
                // Player can become grounded with a partial rappel state based on object height
                // If player is grounded then reset back to inactive state
                if (GameManager.Instance.PlayerMotor.IsGrounded)
                {
                    ResetRappelState();
                    return;
                }
            }

            InitialSetRappelType();

            bool    inputBackward = InputManager.Instance.HasAction(InputManager.Actions.MoveBackwards);
            Vector3 origin        = Vector3.zero;
            Vector3 direction     = -controller.transform.forward;

            #region Scan For AdjacentSurface
            if (inputBackward)
            {
                // check from different origins to find different surfaces
                if (!climbingMotor.IsClimbing)
                {
                    origin = controller.transform.position + Vector3.down * (0.25f * controller.height) + controller.transform.forward * (0.8f * controller.radius);
                }
                else
                {
                    origin = controller.transform.position + Vector3.up * (0.25f * controller.height) + controller.transform.forward * (0.8f * controller.radius);
                }

                playerScanner.FindAdjacentSurface(origin, direction, PlayerMoveScanner.RotationDirection.YZCounterClockwise);
            }
            #endregion

            // the only time Ground closeness can cancel the start of the rappel is when we are
            // going to rappel down and behind to a wall
            if (InitialTooCloseToGround(rappelDirection))
            {
                IsRappelling = false;
                return;
            }

            if (rappelStage == RappelStage.Activated)
            {
                DaggerfallUI.AddHUDText(UserInterfaceWindows.HardStrings.rappelMode);
                rappelStage = RappelStage.Swooping;
                InitialSetGrappleDirection();

                swoopBasePosition = controller.transform.position;
                rappelTimer       = 0f;
                measure           = null;
            }

            // Rappel swooping
            if (rappelStage == RappelStage.Swooping)
            {
                player.TallySkill(DFCareer.Skills.Climbing, 1);
                Vector3 swoopDirection = grappleDirection;
                // if we are rappelling under to ceiling, grappledirection is different so use adjacentSurfaceRay
                // direction to get right direction to go under the ceiling.
                if (rappelDirection == RappelDirection.DownUnder || rappelDirection == RappelDirection.FrontUp)
                {
                    swoopDirection = playerScanner.WallDetachedVector;
                }
                rappelTimer += Time.deltaTime;

                switch (rappelDirection)
                {
                case RappelDirection.DownBehind:
                    CurlDown(swoopBasePosition, swoopDirection);
                    break;

                case RappelDirection.UpBehind:
                    CurlOver(swoopBasePosition, swoopDirection);
                    break;

                //case RappelDirection.DownUnder:
                //    CurlUnder(swoopBasePosition, swoopDirection);
                //    break;
                case RappelDirection.FrontUp:
                    if (updateSwoopBasePosition)
                    {       // enables player to bottom out on DownUnder and continue FrontUp
                        swoopBasePosition       = controller.transform.position;
                        updateSwoopBasePosition = false;
                        rappelTimer             = 0;
                    }
                    CurlUpHalf(swoopBasePosition, swoopDirection);
                    break;

                default:
                    break;
                }

                controller.transform.position = rappelPosition;
            }

            if (rappelStage == RappelStage.Grappling)
            // perform horizontal measurement-based Wall-grapple direction or vertical for ceiling
            {
                // if measurement hasn't started, start measuring grapple-to-surface movement
                if (measure == null)
                {
                    measure = new VectorMeasurement(controller.transform.position);
                }

                if (!(/*hangingMotor.IsHanging ||*/ climbingMotor.IsClimbing) &&
                    measure.Distance(controller.transform.position) < 1f)
                {
                    // Auto move toward surface to grab
                    float speed = speedChanger.GetBaseSpeed();

                    grappleDirection = grappleDirection.normalized * speed * 1.15f;
                    groundMotor.MoveWithMovingPlatform(grappleDirection);
                }
                else // if we've moved past the distance limit
                {
                    ResetRappelState();
                }
            }
        }
コード例 #7
0
        public void ClimbingCheck(ref CollisionFlags collisionFlags)
        {
            // Get pre-movement position for climbing check
            lastHorizontalPosition = new Vector2(controller.transform.position.x, controller.transform.position.z);

            if (isClimbing)
            {
                collisionFlags = CollisionFlags.Sides;
            }
            // Get collision flags for swimming as well, so it's possible to climb out of water TODO: Collision flags from swimming aren't working
            else if (levitateMotor.IsSwimming)
            {
                collisionFlags = levitateMotor.CollisionFlags;
            }

            // Climbing
            uint gameMinutes = DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.ToClassicDaggerfallTime();

            if (!InputManager.Instance.HasAction(InputManager.Actions.MoveForwards) ||
                (collisionFlags & CollisionFlags.Sides) == 0 ||
                failedClimbingCheck ||
                levitateMotor.IsLevitating ||
                playerMotor.IsRiding ||
                Vector2.Distance(lastHorizontalPosition, new Vector2(controller.transform.position.x, controller.transform.position.z)) >= (0.003f))    // Approximation based on observing classic in-game
            {
                isClimbing = false;
                showClimbingModeMessage = true;
                climbingStartTimer      = 0;
                timeOfLastClimbingCheck = gameMinutes;
            }
            else
            {
                if (climbingStartTimer <= (playerMotor.systemTimerUpdatesPerSecond * 14))
                {
                    climbingStartTimer += Time.deltaTime;
                }
                else
                {
                    if (!isClimbing)
                    {
                        if (showClimbingModeMessage)
                        {
                            DaggerfallUI.AddHUDText(UserInterfaceWindows.HardStrings.climbingMode);
                        }
                        // Disable further showing of climbing mode message until current climb attempt is stopped
                        // to keep it from filling message log
                        showClimbingModeMessage = false;
                        isClimbing = true;
                    }

                    // Initial check to start climbing
                    if ((gameMinutes - timeOfLastClimbingCheck) > 18)
                    {
                        Entity.PlayerEntity player = GameManager.Instance.PlayerEntity;
                        player.TallySkill(DFCareer.Skills.Climbing, 1);
                        timeOfLastClimbingCheck = gameMinutes;
                        if (UnityEngine.Random.Range(1, 101) > 95)
                        {
                            if (UnityEngine.Random.Range(1, 101) > player.Skills.GetLiveSkillValue(DFCareer.Skills.Climbing))
                            {
                                isClimbing          = false;
                                failedClimbingCheck = true;
                            }
                        }
                    }
                }
            }

            if (isClimbing)
            {
                ClimbMovement();
            }
        }
コード例 #8
0
        void FixedUpdate()
        {
            // Clear movement
            if (cancelMovement)
            {
                moveDirection  = Vector3.zero;
                cancelMovement = false;
                ClearActivePlatform();
                ClearFallingDamage();
                return;
            }

            // Handle freeze movement
            if (freezeMotor > 0)
            {
                freezeMotor -= Time.deltaTime;
                if (freezeMotor <= 0)
                {
                    freezeMotor    = 0;
                    CancelMovement = true;
                }
                return;
            }

            if (isClimbing)
            {
                collisionFlags = CollisionFlags.Sides;
            }
            // Get collision flags for swimming as well, so it's possible to climb out of water TODO: Collision flags from swimming aren't working
            else if (fakeLevitate.IsSwimming)
            {
                collisionFlags = fakeLevitate.CollisionFlags;
            }

            // Climbing
            uint gameMinutes = DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.ToClassicDaggerfallTime();

            if (!InputManager.Instance.HasAction(InputManager.Actions.MoveForwards) ||
                (collisionFlags & CollisionFlags.Sides) == 0 ||
                failedClimbingCheck ||
                fakeLevitate.IsLevitating ||
                isRiding ||
                Vector2.Distance(lastHorizontalPosition, new Vector2(controller.transform.position.x, controller.transform.position.z)) >= (0.003f))    // Approximation based on observing classic in-game
            {
                isClimbing = false;
                showClimbingModeMessage = true;
                climbingStartTimer      = 0;
                timeOfLastClimbingCheck = gameMinutes;
            }
            else
            {
                if (climbingStartTimer <= (systemTimerUpdatesPerSecond * 14))
                {
                    climbingStartTimer += Time.deltaTime;
                }
                else
                {
                    if (!isClimbing)
                    {
                        if (showClimbingModeMessage)
                        {
                            DaggerfallUI.AddHUDText(UserInterfaceWindows.HardStrings.climbingMode);
                        }
                        // Disable further showing of climbing mode message until current climb attempt is stopped
                        // to keep it from filling message log
                        showClimbingModeMessage = false;
                        isClimbing = true;
                    }

                    // Initial check to start climbing
                    if ((gameMinutes - timeOfLastClimbingCheck) > 18)
                    {
                        Entity.PlayerEntity player = GameManager.Instance.PlayerEntity;
                        player.TallySkill(DFCareer.Skills.Climbing, 1);
                        timeOfLastClimbingCheck = gameMinutes;
                        if (UnityEngine.Random.Range(1, 101) > 95)
                        {
                            if (UnityEngine.Random.Range(1, 101) > player.Skills.GetLiveSkillValue(DFCareer.Skills.Climbing))
                            {
                                isClimbing          = false;
                                failedClimbingCheck = true;
                            }
                        }
                    }
                }
            }

            if (isClimbing)
            {
                falling = false;
                ClimbMovement();
            }

            // Do nothing if player fake levitating/swimming or climbing - replacement motor will take over movement for levitating/swimming
            if (fakeLevitate && (fakeLevitate.IsLevitating || fakeLevitate.IsSwimming) || isClimbing)
            {
                return;
            }

            //float inputX = Input.GetAxis("Horizontal");
            //float inputY = Input.GetAxis("Vertical");
            float inputX = InputManager.Instance.Horizontal;
            float inputY = InputManager.Instance.Vertical;
            // If both horizontal and vertical are used simultaneously, limit speed (if allowed), so the total doesn't exceed normal move speed
            float inputModifyFactor = (inputX != 0.0f && inputY != 0.0f && limitDiagonalSpeed) ? .7071f : 1.0f;

            // Player assumed to be in movement for now
            standingStill = false;

            if (grounded)
            {
                // Set standing still while grounded flag
                // Casting moveDirection to a Vector2 so constant downward force of gravity not included in magnitude
                standingStill = (new Vector2(moveDirection.x, moveDirection.z).magnitude == 0);

                if (jumping)
                {
                    jumping = false;
                }
                bool sliding = false;
                // See if surface immediately below should be slid down. We use this normally rather than a ControllerColliderHit point,
                // because that interferes with step climbing amongst other annoyances
                if (Physics.Raycast(myTransform.position, -Vector3.up, out hit, rayDistance))
                {
                    if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
                    {
                        sliding = true;
                    }
                }
                // However, just raycasting straight down from the center can fail when on steep slopes
                // So if the above raycast didn't catch anything, raycast down from the stored ControllerColliderHit point instead
                else
                {
                    Physics.Raycast(contactPoint + Vector3.up, -Vector3.up, out hit);
                    if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
                    {
                        sliding = true;
                    }
                }

                // If we were falling, and we fell a vertical distance greater than the threshold, run a falling damage routine
                if (falling)
                {
                    falling = false;
                    float fallDistance = fallStartLevel - myTransform.position.y;
                    if (fallDistance > fallingDamageThreshold)
                    {
                        FallingDamageAlert(fallDistance);
                    }
                    else if (fallDistance > fallingDamageThreshold / 2f)
                    {
                        BadFallDetected(fallDistance);
                    }
                    //if (myTransform.position.y < fallStartLevel - fallingDamageThreshold)
                    //    FallingDamageAlert(fallDistance);
                }

                // Get walking/crouching/riding speed
                speed = GetBaseSpeed();

                if (!riding)
                {
                    if (!isCrouching)
                    {
                        controller.height = standingHeight;
                    }

                    try
                    {
                        // If running isn't on a toggle, then use the appropriate speed depending on whether the run button is down
                        if (!toggleRun && InputManager.Instance.HasAction(InputManager.Actions.Run))
                        {
                            speed = GetRunSpeed(speed);
                        }
                    }
                    catch
                    {
                        speed = GetRunSpeed(speed);
                    }
                }

                // Handle sneak key. Reduces movement speed to half, then subtracts 1 in classic speed units
                if (InputManager.Instance.HasAction(InputManager.Actions.Sneak))
                {
                    speed /= 2;
                    speed -= (1 / classicToUnitySpeedUnitRatio);
                }

                // If sliding (and it's allowed), or if we're on an object tagged "Slide", get a vector pointing down the slope we're on
                if ((sliding && slideWhenOverSlopeLimit) || (slideOnTaggedObjects && hit.collider.tag == "Slide"))
                {
                    Vector3 hitNormal = hit.normal;
                    moveDirection = new Vector3(hitNormal.x, -hitNormal.y, hitNormal.z);
                    Vector3.OrthoNormalize(ref hitNormal, ref moveDirection);
                    moveDirection *= slideSpeed;
                    playerControl  = false;
                }
                // Otherwise recalculate moveDirection directly from axes, adding a bit of -y to avoid bumping down inclines
                else
                {
                    moveDirection = new Vector3(inputX * inputModifyFactor, -antiBumpFactor, inputY * inputModifyFactor);
                    moveDirection = myTransform.TransformDirection(moveDirection) * speed;
                    playerControl = true;
                }

                try
                {
                    // Jump! But only if the jump button has been released and player has been grounded for a given number of frames
                    if (!InputManager.Instance.HasAction(InputManager.Actions.Jump))
                    {
                        jumpTimer++;
                    }
                    //if (!Input.GetButton("Jump"))
                    //    jumpTimer++;
                    else if (jumpTimer >= antiBunnyHopFactor)
                    {
                        moveDirection.y = jumpSpeed;
                        jumpTimer       = 0;
                        jumping         = true;

                        // Modify crouching jump speed
                        if (isCrouching)
                        {
                            moveDirection.y *= crouchingJumpDelta;
                        }
                    }
                    else
                    {
                        jumping = false;
                    }
                }
                catch
                {
                }
            }
            else
            {
                // If we stepped over a cliff or something, set the height at which we started falling
                if (!falling)
                {
                    falling        = true;
                    fallStartLevel = myTransform.position.y;
                }

                // If air control is allowed, check movement but don't touch the y component
                if (airControl && playerControl)
                {
                    moveDirection.x = inputX * speed * inputModifyFactor;
                    moveDirection.z = inputY * speed * inputModifyFactor;
                    moveDirection   = myTransform.TransformDirection(moveDirection);
                }
            }

            // Apply gravity
            moveDirection.y -= gravity * Time.deltaTime;

            // If we hit something above us AND we are moving up, reverse vertical movement
            if ((controller.collisionFlags & CollisionFlags.Above) != 0)
            {
                if (moveDirection.y > 0)
                {
                    moveDirection.y = -moveDirection.y;
                }
            }

            // Moving platform support
            if (activePlatform != null)
            {
                var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
                var moveDistance           = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
                if (moveDistance != Vector3.zero)
                {
                    controller.Move(moveDistance);
                }
                //lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;

                // If you want to support moving platform rotation as well:
                var newGlobalPlatformRotation = activePlatform.rotation * activeLocalPlatformRotation;
                var rotationDiff = newGlobalPlatformRotation * Quaternion.Inverse(activeGlobalPlatformRotation);

                // Prevent rotation of the local up vector
                rotationDiff = Quaternion.FromToRotation(rotationDiff * transform.up, transform.up) * rotationDiff;

                transform.rotation = rotationDiff * transform.rotation;
            }
            //else
            //{
            //    lastPlatformVelocity = Vector3.zero;
            //}

            activePlatform = null;

            // Move the controller, and set grounded true or false depending on whether we're standing on something
            collisionFlags = controller.Move(moveDirection * Time.deltaTime);

            // Get pre-movement position for climbing check
            lastHorizontalPosition = new Vector2(controller.transform.position.x, controller.transform.position.z);

            grounded = (collisionFlags & CollisionFlags.Below) != 0;

            // Moving platforms support
            if (activePlatform != null)
            {
                activeGlobalPlatformPoint = transform.position;
                activeLocalPlatformPoint  = activePlatform.InverseTransformPoint(transform.position);

                // If you want to support moving platform rotation as well:
                activeGlobalPlatformRotation = transform.rotation;
                activeLocalPlatformRotation  = Quaternion.Inverse(activePlatform.rotation) * transform.rotation;
            }
        }