Esempio n. 1
0
        /// <summary>
        /// This method determines the proper movement related animation
        /// </summary>
        private string GetMovementAnimation()
        {
            const float SLOWFLY_DELAY = 15f;
            const float STANDUP_TIME  = 2f;
            const float BRUSH_TIME    = 3.5f;

            const float SOFTLAND_FORCE = 80;

            const float PREJUMP_DELAY = 0.35f;

            #region Inputs

            if (m_scenePresence.SitGround)
            {
                return("SIT_GROUND_CONSTRAINED");
            }
            AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
            PhysicsActor actor = m_scenePresence.PhysicsActor;

            // Create forward and left vectors from the current avatar rotation

            /*
             *          Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation);
             *          Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix);
             *          Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
             */

            Vector3 fwd  = Vector3.UnitX * m_scenePresence.Rotation;
            Vector3 left = Vector3.UnitY * m_scenePresence.Rotation;

            // Check control flags
            bool heldForward =
                (((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) || ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS));
            bool yawPos        = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) == AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS;
            bool yawNeg        = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG;
            bool heldBack      = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG;
            bool heldLeft      = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS;
            bool heldRight     = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
            bool heldTurnLeft  = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
            bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
            bool heldUp        = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
            bool heldDown      = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
            //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
            //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;

            // Direction in which the avatar is trying to move
            Vector3 move = Vector3.Zero;
            if (heldForward)
            {
                move.X += fwd.X; move.Y += fwd.Y;
            }
            if (heldBack)
            {
                move.X -= fwd.X; move.Y -= fwd.Y;
            }
            if (heldLeft)
            {
                move.X += left.X; move.Y += left.Y;
            }
            if (heldRight)
            {
                move.X -= left.X; move.Y -= left.Y;
            }
            if (heldUp)
            {
                move.Z += 1;
            }
            if (heldDown)
            {
                move.Z -= 1;
            }
            bool  jumping      = m_animTickJump != 0;
            float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;

            if (heldTurnLeft && yawPos && !heldForward &&
                !heldBack && !jumping && actor != null &&
                !actor.Flying && move.Z == 0 &&
                fallVelocity == 0.0f && !heldUp &&
                !heldDown && move.CompareTo(Vector3.Zero) == 0)
            {
                return("TURNLEFT");
            }
            if (heldTurnRight && yawNeg && !heldForward &&
                !heldBack && !jumping && actor != null &&
                !actor.Flying && move.Z == 0 &&
                fallVelocity == 0.0f && !heldUp &&
                !heldDown && move.CompareTo(Vector3.Zero) == 0)
            {
                return("TURNRIGHT");
            }

            // Is the avatar trying to move?
            //            bool moving = (move != Vector3.Zero);

            #endregion Inputs

            #region Standup

            float standupElapsed = (float)(Util.EnvironmentTickCount() - m_animTickStandup) / 1000f;
            if (standupElapsed < STANDUP_TIME &&
                m_useSplatAnimation)
            {
                // Falling long enough to trigger the animation
                m_scenePresence.AllowMovement         = false;
                m_scenePresence.PhysicsActor.Velocity = Vector3.Zero;
                return("STANDUP");
            }
            else if (standupElapsed < BRUSH_TIME &&
                     m_useSplatAnimation)
            {
                m_scenePresence.AllowMovement = false;
                return("BRUSH");
            }
            else if (m_animTickStandup != 0)
            {
                m_animTickStandup             = 0;
                m_scenePresence.AllowMovement = true;
            }

            #endregion Standup

            #region Flying

//            if (actor != null && actor.Flying)
            if (actor != null && (m_scenePresence.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) == (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY)
            {
                m_animTickFall = 0;
                m_animTickJump = 0;
                if (move.X != 0f || move.Y != 0f)
                {
                    if (move.Z == 0)
                    {
                        if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
                            actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
                        {
                            return("SWIM_FORWARD");
                        }
                        else
                        {
                            if (m_timesBeforeSlowFlyIsOff < SLOWFLY_DELAY)
                            {
                                m_timesBeforeSlowFlyIsOff++;
                                return("FLYSLOW");
                            }
                            else
                            {
                                return("FLY");
                            }
                        }
                    }
                    else if (move.Z > 0)
                    {
                        if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
                            actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
                        {
                            return("SWIM_UP");
                        }
                        else
                        {
                            return("FLYSLOW");
                        }
                    }
                    if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
                        actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
                    {
                        return("SWIM_DOWN");
                    }
                    else
                    {
                        return("FLY");
                    }
                }
                else if (move.Z > 0f)
                {
                    //This is for the slow fly timer
                    m_timesBeforeSlowFlyIsOff = 0;
                    if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
                        actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
                    {
                        return("SWIM_UP");
                    }
                    else
                    {
                        return("HOVER_UP");
                    }
                }
                else if (move.Z < 0f)
                {
                    //This is for the slow fly timer
                    m_timesBeforeSlowFlyIsOff = 0;
                    if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
                        actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
                    {
                        return("SWIM_DOWN");
                    }
                    else
                    {
                        ITerrainChannel channel      = m_scenePresence.Scene.RequestModuleInterface <ITerrainChannel>();
                        float           groundHeight = channel.GetNormalizedGroundHeight((int)m_scenePresence.AbsolutePosition.X, (int)m_scenePresence.AbsolutePosition.Y);
                        if (actor != null && (m_scenePresence.AbsolutePosition.Z - groundHeight) < 2)
                        {
                            return("LAND");
                        }
                        else
                        {
                            return("HOVER_DOWN");
                        }
                    }
                }
                else
                {
                    //This is for the slow fly timer
                    m_timesBeforeSlowFlyIsOff = 0;
                    if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
                        actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
                    {
                        return("SWIM_HOVER");
                    }
                    else
                    {
                        return("HOVER");
                    }
                }
            }

            m_timesBeforeSlowFlyIsOff = 0;
            #endregion Flying

            #region Falling/Floating/Landing

            if (actor == null && !jumping && move.Z == 0 || (actor != null && (!actor.CollidingObj && !actor.CollidingGround) && m_scenePresence.Velocity.Z < -2))
            {
                //Always return falldown immediately as there shouldn't be a waiting period
                if (m_animTickFall == 0)
                {
                    m_animTickFall = Util.EnvironmentTickCount();
                }
                return("FALLDOWN");
            }

            #endregion Falling/Floating/Landing

            #region Ground Movement

            //This needs to be in front of landing, otherwise you get odd landing effects sometimes when one jumps
            // -- Revolution
            if (move.Z > 0f || m_animTickJump != 0)
            {
                if (m_usePreJump)
                {
                    //This is to check to make sure they arn't trying to fly up by holding down jump
                    if ((m_scenePresence.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) == 0)
                    {
                        // Jumping
                        float jumpChange = (((float)Util.EnvironmentTickCount()) - m_animTickJump) / 1000;
                        if (!jumping || (jumpChange < PREJUMP_DELAY && m_animTickJump > 0))
                        {
                            // Begin prejump
                            if (m_animTickJump == 0)
                            {
                                m_animTickJump = (float)Util.EnvironmentTickCount();
                            }
                            return("PREJUMP");
                        }
                        else if (m_animTickJump != 0)
                        {
                            #region PreJump

                            /*m_hasPreJumped = true;
                             * if (m_scenePresence.PreJumpForce.Z != 0 && !m_hasJumpAddedForce)
                             * {
                             *  m_hasJumpAddedForce = true;
                             *  m_scenePresence.PreJumpForce.X /= 2f;
                             *  m_scenePresence.PreJumpForce.Y /= 2f;
                             *  //m_scenePresence.PreJumpForce.Z *= 1.75f;
                             *  if(m_scenePresence.Scene.m_UseNewStyleMovement)
                             *      m_scenePresence.m_velocityIsDecaying = false;
                             *
                             *  m_scenePresence.PhysicsActor.Velocity = m_scenePresence.PreJumpForce;
                             *  //m_scenePresence.m_forceToApply = m_scenePresence.PreJumpForce;
                             *
                             *  m_scenePresence.PreJumpForce = new Vector3(
                             *      m_scenePresence.PreJumpForce.X > 0 ? 7 : (m_scenePresence.PreJumpForce.X < 0 ? -3 : 0),
                             *      m_scenePresence.PreJumpForce.Y > 0 ? 7 : (m_scenePresence.PreJumpForce.Y < 0 ? -3 : 0),
                             *      0);
                             *
                             *  m_jumpZ = 0;
                             *  return "JUMP";
                             * }
                             *
                             * if (jumpChange >= 3) //Kill this if it takes too long
                             * {
                             *  m_scenePresence.PhysicsActor.Velocity = Vector3.Zero;
                             *  m_animTickJump = 0;
                             *  m_scenePresence.AllowMovement = true;
                             *  if (m_scenePresence.Scene.m_UseNewStyleMovement)
                             *      m_scenePresence.m_velocityIsDecaying = true;
                             *  m_animTickNextJump = Util.TickCount();
                             *  return "STAND";
                             * }
                             *
                             * //Check #1: Going up.
                             * if (m_jumpZ == 0 &&
                             *  m_scenePresence.Velocity.Z >= -0.3)
                             * {
                             *  //This stops from double jump when you jump straight up and doesn't break jumping with X and Y velocity
                             *  //This particular check makes sure that we do not break jumping straight up
                             *  if (!m_scenePresence.m_forceToApply.HasValue ||
                             *       (m_scenePresence.m_forceToApply.HasValue &&
                             *       m_scenePresence.m_forceToApply.Value.X != 0 &&
                             *       m_scenePresence.m_forceToApply.Value.Y != 0))
                             *  {
                             *      m_scenePresence.PreJumpForce.Z = -1f;
                             *
                             *      m_scenePresence.m_forceToApply = m_scenePresence.PreJumpForce;
                             *  }
                             *
                             *  m_scenePresence.AllowMovement = false;
                             *  return "JUMP";
                             * }
                             * //Check #2: Coming down
                             * else if (m_jumpZ <= 1 &&
                             *  m_scenePresence.Velocity.Z < 0)
                             * {
                             *  m_jumpZ = 1;
                             *  //This stops from double jump when you jump straight up and doesn't break jumping with X and Y velocity
                             *  //This particular check makes sure that we do not break jumping straight up
                             *  if (!m_scenePresence.m_forceToApply.HasValue ||
                             *       (m_scenePresence.m_forceToApply.HasValue &&
                             *       m_scenePresence.m_forceToApply.Value.X != 0 &&
                             *       m_scenePresence.m_forceToApply.Value.Y != 0))
                             *  {
                             *      m_scenePresence.PreJumpForce.Z = -0.1f;
                             *
                             *      m_scenePresence.m_forceToApply = m_scenePresence.PreJumpForce;
                             *  }
                             *
                             *  m_scenePresence.AllowMovement = false;
                             *  return "JUMP";
                             * }
                             * else
                             * {
                             *  //m_scenePresence.m_forceToApply = Vector3.Zero;
                             *  m_scenePresence.PhysicsActor.Velocity = Vector3.Zero;
                             *  m_animTickJump = 0;
                             *  m_scenePresence.AllowMovement = true;
                             *  if (m_scenePresence.Scene.m_UseNewStyleMovement)
                             *      m_scenePresence.m_velocityIsDecaying = true;
                             *  m_animTickNextJump = Util.EnvironmentTickCount();
                             *  return "STAND";
                             * }*/
                            #endregion
                            if (m_scenePresence.PreJumpForce != Vector3.Zero)
                            {
                                Vector3 jumpForce = m_scenePresence.PreJumpForce;
                                m_scenePresence.PreJumpForce = Vector3.Zero;
                                m_scenePresence.AddNewMovement(jumpForce, Quaternion.Identity);
                                m_animTickJump = -42;
                                return("JUMP");
                            }

                            m_animTickJump++;
                            //This never gets hit as velocity is really broken
                            //if (m_scenePresence.Velocity.Z < -0.50)
                            //{
                            //    m_scenePresence.m_forceToApply = Vector3.Zero;
                            //    m_scenePresence.m_overrideUserInput = false;
                            //}
                            return("JUMP");
                        }
                    }
                }
                else
                {
                    // Jumping
                    //float jumpChange = (((float)Util.EnvironmentTickCount()) - m_animTickJump) / 1000;
                    if (!jumping)
                    {
                        m_animTickJump = Util.EnvironmentTickCount();
                        return("JUMP");
                    }
                    else
                    {
                        // Start actual jump
                        if (m_animTickJump > 0)
                        {
                            m_animTickJump = -20;
                            return("JUMP");
                        }

                        m_animTickJump++;
                        return("JUMP");
                    }
                }
            }
            if (m_scenePresence.IsJumping)
            {
                m_scenePresence.IsJumping     = false;
                m_scenePresence.AllowMovement = true;
            }

            if (m_movementAnimation == "FALLDOWN")
            {
                float fallElapsed = (float)(Util.EnvironmentTickCount() - m_animTickFall) / 1000f;
                if (fallElapsed < 0.75)
                {
                    m_animTickFall = Util.EnvironmentTickCount();

                    return("SOFT_LAND");
                }
                else if (fallElapsed < 1.1)
                {
                    m_animTickFall = Util.EnvironmentTickCount();

                    return("LAND");
                }
                else
                {
                    if (m_useSplatAnimation)
                    {
                        m_animTickStandup = Util.EnvironmentTickCount();
                        return("STANDUP");
                    }
                    else
                    {
                        return("LAND");
                    }
                }

                /*//Experimentally found variables, but it makes soft landings look good.
                 * // -- Revolution
                 * //Note: we use m_scenePresence.LastVelocity for a reason! The PhysActor and SP Velocity are both cleared before this is called.
                 *
                 * float Z = m_scenePresence.LastVelocity.Z * m_scenePresence.LastVelocity.Z;
                 * if (Math.Abs(m_scenePresence.LastVelocity.X) < 0.1 && Math.Abs(m_scenePresence.LastVelocity.Y) < 0.1)
                 *  Z *= Z; //If you are falling down, the calculation is different..
                 * if (Z < SOFTLAND_FORCE)
                 * {
                 *  m_animTickFall = Util.EnvironmentTickCount();
                 *
                 *  return "SOFT_LAND";
                 * }
                 * else if (Z < LAND_FORCE)
                 * {
                 *  m_animTickFall = Util.EnvironmentTickCount();
                 *
                 *  return "LAND";
                 * }
                 * else
                 * {
                 *  if (m_scenePresence.Scene.m_useSplatAnimation)
                 *  {
                 *      m_animTickStandup = Util.EnvironmentTickCount();
                 *      return "STANDUP";
                 *  }
                 *  else
                 *      return "LAND";
                 * }*/
            }
            else if (m_movementAnimation == "LAND")
            {
                if (actor.Velocity.Z != 0)
                {
                    if (actor.Velocity.Z < SOFTLAND_FORCE)
                    {
                        return("LAND");
                    }
                    return("SOFT_LAND");
                }
            }

            m_animTickFall = 0;

            if (move.Z <= 0f)
            {
                // Not jumping
                m_animTickJump = 0;

                if (move.X != 0f || move.Y != 0f ||
                    actor.Velocity.X != 0 && actor.Velocity.Y != 0)
                {
                    // Walking / crouchwalking / running
                    if (move.Z < 0f)
                    {
                        return("CROUCHWALK");
                    }
                    else if (m_scenePresence.SetAlwaysRun)
                    {
                        return("RUN");
                    }
                    else
                    {
                        return("WALK");
                    }
                }
                else
                {
                    // Not walking
                    if (move.Z < 0f)
                    {
                        return("CROUCH");
                    }
                    else
                    {
                        return("STAND");
                    }
                }
            }

            #endregion Ground Movement

            return(m_movementAnimation);
        }