/// <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); }