public string GetMovementAnimation ()
{
const float STANDUP_TIME = 2f;
const float BRUSH_TIME = 3.5f;
const float FALL_AFTER_MOVE_TIME = 0.75f;
const float SOFTLAND_FORCE = 80;
#region Inputs
if (m_scenePresence.SitGround) {
return "SIT_GROUND_CONSTRAINED";
}
var controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
PhysicsActor actor = m_scenePresence.PhysicsActor;
// Create forward and left vectors from the current avatar rotation
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;
}
float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
if (heldTurnLeft && yawPos && !heldForward &&
!heldBack && actor != null && !actor.IsJumping &&
!actor.Flying && Util.ApproxZero(move.Z) &&
Util.ApproxZero (fallVelocity) && !heldUp &&
!heldDown && move.CompareTo (Vector3.Zero) == 0) {
return "TURNLEFT";
}
if (heldTurnRight && yawNeg && !heldForward &&
!heldBack && actor != null && !actor.IsJumping &&
!actor.Flying && Util.ApproxZero (move.Z) &&
Util.ApproxZero (fallVelocity) && !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 = (Util.EnvironmentTickCount () - m_animTickStandup) / 1000f;
if (m_scenePresence.PhysicsActor != null && standupElapsed < STANDUP_TIME &&
m_useSplatAnimation) {
// Falling long enough to trigger the animation
m_scenePresence.FallenStandUp = true;
m_scenePresence.PhysicsActor.Velocity = Vector3.Zero;
return "STANDUP";
}
// need the brush off?
if (standupElapsed < BRUSH_TIME && m_useSplatAnimation) {
m_scenePresence.FallenStandUp = true;
return "BRUSH";
}
if (Util.NotZero(m_animTickStandup) || m_scenePresence.FallenStandUp) {
m_scenePresence.FallenStandUp = false;
m_animTickStandup = 0;
}
#endregion Standup
#region Flying
if (actor != null &&
(m_scenePresence.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) ==
(uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY || m_scenePresence.ForceFly) {
m_animTickWalk = 0;
m_animTickFall = 0;
if (Util.NotZero(move.X) || Util.NotZero(move.Y)) {
// level?
if (Util.NotZero(move.Z)) {
if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight) {
return "SWIM_FORWARD";
}
// must be flying then
if (m_timesBeforeSlowFlyIsOff < SLOWFLY_DELAY) {
m_timesBeforeSlowFlyIsOff++;
return "FLYSLOW";
}
return "FLY";
}
// going up then...
if (move.Z > 0) {
if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
return "SWIM_UP";
// easy does it
return "FLYSLOW";
}
if (m_scenePresence.Scene.PhysicsScene.UseUnderWaterPhysics &&
actor.Position.Z < m_scenePresence.Scene.RegionInfo.RegionSettings.WaterHeight)
return "SWIM_DOWN";
// in the wild blue yonder
return "FLY";
}
// moving left/right but going up as well?
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";
// going up...
return "HOVER_UP";
}
// mabye moving down then?
if (move.Z < 0f) {
wasLastFlying = true;
//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";
ITerrainChannel channel = m_scenePresence.Scene.RequestModuleInterface<ITerrainChannel> ();
if (channel != null) {
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";
return "HOVER_DOWN";
}
// no ground here...
return "HOVER_DOWN";
}
//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";
return "HOVER";
}
m_timesBeforeSlowFlyIsOff = 0;
#endregion Flying
#region Jumping
if (actor != null && actor.IsJumping) {
return "JUMP";
}
if (actor != null && actor.IsPreJumping) {
return "PREJUMP";
}
#endregion
#region Falling/Floating/Landing
float walkElapsed = (Util.EnvironmentTickCount () - m_animTickWalk) / 1000f;
if (actor != null && actor.IsPhysical && !actor.IsJumping && (!actor.IsColliding) && !actor.Flying && actor.TargetVelocity != Vector3.Zero/* && actor.Velocity.Z < -2*/ &&
(walkElapsed > FALL_AFTER_MOVE_TIME || Util.ApproxZero(m_animTickWalk)))//For if they user is walking off something, or they are falling
{
//Always return falldown immediately as there shouldn't be a waiting period
if (Util.ApproxZero(m_animTickFall))
m_animTickFall = Util.EnvironmentTickCount ();
return "FALLDOWN";
}
#endregion Falling/Floating/Landing
#region Ground Movement
if (m_movementAnimation == "FALLDOWN") {
float fallElapsed = (Util.EnvironmentTickCount () - m_animTickFall) / 1000f;
// soft landing?
if (fallElapsed < 0.75) {
m_animTickFall = Util.EnvironmentTickCount ();
return "SOFT_LAND";
}
// a bit harder then?
if (actor != null &&
(fallElapsed < 1.1 ||
(Math.Abs (actor.Velocity.X) > 1 &&
Math.Abs (actor.Velocity.Y) > 1 &&
actor.Velocity.Z < 3)
)
) {
m_animTickFall = Util.EnvironmentTickCount ();
return "LAND";
}
// maybe a hard one...
if (m_useSplatAnimation) {
m_animTickStandup = Util.EnvironmentTickCount ();
return "STANDUP";
}
// just a simple landing
return "LAND";
}
// landing then
if (m_movementAnimation == "LAND") {
if (actor != null && actor.Velocity.Z < 0) {
if (actor.Velocity.Z < SOFTLAND_FORCE)
return "LAND";
return "SOFT_LAND";
}
//return "LAND";
}
m_animTickFall = 0;
if (move.Z <= 0f) {
if (actor != null &&
(Util.NotZero(move.X) || Util.NotZero(move.Y) ||
(Util.NotZero(actor.Velocity.X) && Util.NotZero(actor.Velocity.Y))
)
) {
wasLastFlying = false;
if (actor.IsColliding)
m_animTickWalk = Util.EnvironmentTickCount ();
// Walking / crouchwalking / running
if (move.Z < 0f)
return "CROUCHWALK";
// always run?
if (m_scenePresence.SetAlwaysRun)
return "RUN";
// must be walking then
return "WALK";
}
// Not walking
if (move.Z < 0f && !wasLastFlying)
return "CROUCH";
return "STAND";
}
#endregion Ground Movement
// none of the above so just continue the last animation
return m_movementAnimation;
}