/// <summary> /// Builds an AgentUpdate packet entirely from parameters. This /// will not touch the state of Self.Movement or /// Self.Movement.Camera in any way /// </summary> /// <param name="controlFlags"></param> /// <param name="position"></param> /// <param name="forwardAxis"></param> /// <param name="leftAxis"></param> /// <param name="upAxis"></param> /// <param name="bodyRotation"></param> /// <param name="headRotation"></param> /// <param name="farClip"></param> /// <param name="reliable"></param> /// <param name="flags"></param> /// <param name="state"></param> public void SendManualUpdate(AgentManager.ControlFlags controlFlags, Vector3 position, Vector3 forwardAxis, Vector3 leftAxis, Vector3 upAxis, Quaternion bodyRotation, Quaternion headRotation, float farClip, AgentFlags flags, AgentState state, bool reliable) { // Since version 1.40.4 of the Linden simulator, sending this update // causes corruption of the agent position in the simulator if (Client.Network.CurrentSim != null && (!Client.Network.CurrentSim.HandshakeComplete)) { return; } AgentUpdatePacket update = new AgentUpdatePacket(); update.AgentData.AgentID = Client.Self.AgentID; update.AgentData.SessionID = Client.Self.SessionID; update.AgentData.BodyRotation = bodyRotation; update.AgentData.HeadRotation = headRotation; update.AgentData.CameraCenter = position; update.AgentData.CameraAtAxis = forwardAxis; update.AgentData.CameraLeftAxis = leftAxis; update.AgentData.CameraUpAxis = upAxis; update.AgentData.Far = farClip; update.AgentData.ControlFlags = (uint)controlFlags; update.AgentData.Flags = (byte)flags; update.AgentData.State = (byte)state; update.Header.Reliable = reliable; Client.Network.SendPacket(update); }
public void OnNewMovement(ref AgentManager.ControlFlags flags) { lock (scriptedcontrols) { if (scriptedcontrols.Count > 0) { SendControlToScripts((uint)flags); flags = RemoveIgnoredControls(flags, IgnoredControls); } } }
void MoveCamera() { while (running) { if (client.Network.Connected) { // TWEAK: Randomize far distance to force an interest list recomputation float far = (float)(random.NextDouble() * 252d + 4d); // Random small movements AgentManager.ControlFlags flags = AgentManager.ControlFlags.NONE; if (far < 96f) { flags |= AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; } else if (far < 196f) { flags |= AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; } else if (far < 212f) { flags |= AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; } else { flags |= AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG; } // Randomly change the camera position Vector3 pos = RandomPosition(); client.Self.Movement.SendManualUpdate( flags, pos, Vector3.UnitZ, Vector3.UnitX, Vector3.UnitY, Quaternion.Identity, Quaternion.Identity, far, AgentFlags.None, AgentState.None, false); } Thread.Sleep(500); } }
/// <summary> /// Builds an AgentUpdate packet entirely from parameters. This /// will not touch the state of Self.Movement or /// Self.Movement.Camera in any way /// </summary> /// <param name="controlFlags"></param> /// <param name="position"></param> /// <param name="forwardAxis"></param> /// <param name="leftAxis"></param> /// <param name="upAxis"></param> /// <param name="bodyRotation"></param> /// <param name="headRotation"></param> /// <param name="farClip"></param> /// <param name="reliable"></param> /// <param name="flags"></param> /// <param name="state"></param> public void SendManualUpdate(AgentManager.ControlFlags controlFlags, Vector3 position, Vector3 forwardAxis, Vector3 leftAxis, Vector3 upAxis, Quaternion bodyRotation, Quaternion headRotation, float farClip, AgentFlags flags, AgentState state, bool reliable) { AgentUpdatePacket update = new AgentUpdatePacket(); update.AgentData.AgentID = Client.Self.AgentID; update.AgentData.SessionID = Client.Self.SessionID; update.AgentData.BodyRotation = bodyRotation; update.AgentData.HeadRotation = headRotation; update.AgentData.CameraCenter = position; update.AgentData.CameraAtAxis = forwardAxis; update.AgentData.CameraLeftAxis = leftAxis; update.AgentData.CameraUpAxis = upAxis; update.AgentData.Far = farClip; update.AgentData.ControlFlags = (uint)controlFlags; update.AgentData.Flags = (byte)flags; update.AgentData.State = (byte)state; update.Header.Reliable = reliable; Client.Network.SendPacket(update); }
/// <summary> /// This method determines the proper movement related animation /// </summary> public string GetMovementAnimation() { const float FALL_DELAY = 0.33f; const float PREJUMP_DELAY = 0.25f; #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); // 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 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; } // Is the avatar trying to move? // bool moving = (move != Vector3.Zero); bool jumping = m_animTickJump != 0; #endregion Inputs #region Flying if (actor != null && actor.Flying) { m_animTickFall = 0; m_animTickJump = 0; if (move.X != 0f || move.Y != 0f) { return(m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); } else if (move.Z > 0f) { return("HOVER_UP"); } else if (move.Z < 0f) { if (actor != null && actor.IsColliding) { return("LAND"); } else { return("HOVER_DOWN"); } } else { return("HOVER"); } } #endregion Flying #region Falling/Floating/Landing if (actor == null || !actor.IsColliding) { float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) { // Just started falling m_animTickFall = Environment.TickCount; } else if (!jumping && fallElapsed > FALL_DELAY) { // Falling long enough to trigger the animation return("FALLDOWN"); } else if (m_animTickJump == -1) { m_animTickJump = 0; return("STAND"); } return(m_movementAnimation); } #endregion Falling/Floating/Landing #region Ground Movement if (m_movementAnimation == "FALLDOWN") { m_animTickFall = Environment.TickCount; // TODO: SOFT_LAND support return("LAND"); } else if (m_movementAnimation == "LAND") { float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) { return("LAND"); } } m_animTickFall = 0; if (move.Z > 0f) { // Jumping if (!jumping) { // Begin prejump m_animTickJump = Environment.TickCount; return("PREJUMP"); } else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) { // Start actual jump if (m_animTickJump == -1) { // Already jumping! End the current jump m_animTickJump = 0; return("JUMP"); } m_animTickJump = -1; return("JUMP"); } else { return("JUMP"); } } else { // Not jumping m_animTickJump = 0; if (move.X != 0f || move.Y != 0f) { // 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; }
protected internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored) { if (ignored == ScriptControlled.CONTROL_ZERO) { return(flags); } if ((ignored & ScriptControlled.CONTROL_BACK) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); } if ((ignored & ScriptControlled.CONTROL_FWD) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); } if ((ignored & ScriptControlled.CONTROL_DOWN) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); } if ((ignored & ScriptControlled.CONTROL_UP) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); } if ((ignored & ScriptControlled.CONTROL_LEFT) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); } if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); } if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); } if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); } if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); } if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0) { flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); } //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG return(flags); }
public void CopyFrom(AgentData cAgent) { m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; m_pos = cAgent.Position; m_velocity = cAgent.Velocity; m_CameraCenter = cAgent.Center; //m_avHeight = cAgent.Size.Z; m_CameraAtAxis = cAgent.AtAxis; m_CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; m_DrawDistance = cAgent.Far; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; m_bodyRot = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) m_godLevel = cAgent.GodLevel; m_setAlwaysRun = cAgent.AlwaysRun; uint i = 0; try { if (cAgent.Wearables == null) cAgent.Wearables = new UUID[0]; AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; for (uint n = 0; n < cAgent.Wearables.Length; n += 2) { UUID itemId = cAgent.Wearables[n]; UUID assetId = cAgent.Wearables[n + 1]; wears[i++] = new AvatarWearable(itemId, assetId); } m_appearance.Wearables = wears; Primitive.TextureEntry te; if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); else te = AvatarAppearance.GetDefaultTexture(); if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams(); m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone()); } catch (Exception e) { m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); } // Attachments try { if (cAgent.Attachments != null) { foreach (AttachmentData att in cAgent.Attachments) { m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); } } } catch { } // Animations try { Animator.ResetAnimations(); Animator.Animations.FromArray(cAgent.Anims); } catch { } //cAgent.GroupID = ?? //Groups??? }
private void CopyFrom(AgentData cAgent) { m_callbackURI = cAgent.CallbackURI; // m_log.DebugFormat( // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", // Name, m_scene.RegionInfo.RegionName, m_callbackURI); m_pos = cAgent.Position; m_velocity = cAgent.Velocity; CameraPosition = cAgent.Center; CameraAtAxis = cAgent.AtAxis; CameraLeftAxis = cAgent.LeftAxis; CameraUpAxis = cAgent.UpAxis; ParentUUID = cAgent.ParentPart; PrevSitOffset = cAgent.SitOffset; // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. DrawDistance = cAgent.Far; // DrawDistance = Scene.DefaultDrawDistance; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; Rotation = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) GodLevel = cAgent.GodLevel; SetAlwaysRun = cAgent.AlwaysRun; Appearance = new AvatarAppearance(cAgent.Appearance); if (PhysicsActor != null) { bool isFlying = Flying; RemoveFromPhysicalScene(); AddToPhysicalScene(isFlying); } try { lock (scriptedcontrols) { if (cAgent.Controllers != null) { scriptedcontrols.Clear(); foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); sc.objectID = c.ObjectID; sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; scriptedcontrols[sc.itemID] = sc; } } } } catch { } // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.Anims != null) Animator.Animations.FromArray(cAgent.Anims); if (cAgent.DefaultAnim != null) Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); if (cAgent.AnimState != null) Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(cAgent, this); // This must occur after attachments are copied, as it releases the CompleteMovement() calling thread // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart // script attachments can outrace this thread. lock (m_originRegionIDAccessLock) m_originRegionID = cAgent.RegionID; }
private void CopyFrom(AgentData cAgent) { m_callbackURI = cAgent.CallbackURI; // m_log.DebugFormat( // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", // Name, m_scene.RegionInfo.RegionName, m_callbackURI); m_pos = cAgent.Position; m_velocity = cAgent.Velocity; CameraPosition = cAgent.Center; CameraAtAxis = cAgent.AtAxis; CameraLeftAxis = cAgent.LeftAxis; CameraUpAxis = cAgent.UpAxis; ParentUUID = cAgent.ParentPart; PrevSitOffset = cAgent.SitOffset; // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. DrawDistance = cAgent.Far; //DrawDistance = Scene.DefaultDrawDistance; if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0) { if (Scene.CapsModule != null) { Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds); } KnownRegions = cAgent.ChildrenCapSeeds; } if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; Rotation = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) GodLevel = cAgent.GodLevel; SetAlwaysRun = cAgent.AlwaysRun; Appearance = new AvatarAppearance(cAgent.Appearance); /* bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); if (PhysicsActor != null) { RemoveFromPhysicalScene(); AddToPhysicalScene(isFlying); } */ try { lock (scriptedcontrols) { if (cAgent.Controllers != null) { scriptedcontrols.Clear(); foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); sc.objectID = c.ObjectID; sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; scriptedcontrols[sc.itemID] = sc; } } } } catch { } Animator.ResetAnimations(); Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides); // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.DefaultAnim != null) Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); if (cAgent.AnimState != null) Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); if (cAgent.Anims != null) Animator.Animations.FromArray(cAgent.Anims); if (cAgent.MotionState != 0) Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState; if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(cAgent, this); lock (m_originRegionIDAccessLock) m_originRegionID = cAgent.RegionID; }
private void CopyFrom(AgentData cAgent) { m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; // m_log.DebugFormat( // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", // Name, m_scene.RegionInfo.RegionName, m_callbackURI); m_pos = cAgent.Position; m_velocity = cAgent.Velocity; CameraPosition = cAgent.Center; CameraAtAxis = cAgent.AtAxis; CameraLeftAxis = cAgent.LeftAxis; CameraUpAxis = cAgent.UpAxis; // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. // DrawDistance = cAgent.Far; DrawDistance = Scene.DefaultDrawDistance; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; Rotation = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) GodLevel = cAgent.GodLevel; SetAlwaysRun = cAgent.AlwaysRun; Appearance = new AvatarAppearance(cAgent.Appearance); if (PhysicsActor != null) { bool isFlying = Flying; RemoveFromPhysicalScene(); AddToPhysicalScene(isFlying); } try { lock (scriptedcontrols) { if (cAgent.Controllers != null) { scriptedcontrols.Clear(); foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; scriptedcontrols[sc.itemID] = sc; } } } } catch { } // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.Anims != null) Animator.Animations.FromArray(cAgent.Anims); if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(cAgent, this); }
public virtual void CopyFrom(AgentData cAgent) { try { m_pos = cAgent.Position; if (PhysicsActor != null) { AbsolutePosition = cAgent.Position; PhysicsActor.ForceSetPosition(cAgent.Position); } Velocity = cAgent.Velocity; m_CameraCenter = cAgent.Center; SetHeight(cAgent.Size.Z); m_CameraAtAxis = cAgent.AtAxis; m_CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; DrawDistance = cAgent.Far; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; m_bodyRot = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags) cAgent.ControlFlags; m_savedVelocity = cAgent.Velocity; SpeedModifier = cAgent.Speed; DrawDistance = cAgent.DrawDistance; m_setAlwaysRun = cAgent.AlwaysRun; if (cAgent.IsCrossing) { m_scene.AuthenticateHandler.GetAgentCircuitData(UUID).TeleportFlags |= (uint) TeleportFlags.ViaRegionID; m_scene.AuthenticateHandler.GetAgentCircuitData(UUID).IsChildAgent = false; //We're going to be a root } IAvatarAppearanceModule appearance = RequestModuleInterface<IAvatarAppearanceModule>(); if (appearance != null) { appearance.InitialHasWearablesBeenSent = cAgent.SentInitialWearables; appearance.Appearance = new AvatarAppearance(cAgent.Appearance); } // Animations try { Animator.ResetAnimations(); Animator.Animations.FromArray(cAgent.Anims); } catch { } try { if (cAgent.SittingObjects != null && cAgent.SittingObjects.m_sittingObjectXML != "") { ISceneEntity sceneObject = null; IRegionSerialiserModule mod = Scene.RequestModuleInterface<IRegionSerialiserModule>(); if (mod != null) sceneObject = mod.DeserializeGroupFromXml2(cAgent.SittingObjects.m_sittingObjectXML, Scene); if (sceneObject != null) { //We were sitting on something when we crossed if (Scene.SceneGraph.RestorePrimToScene(sceneObject, false)) { if (sceneObject.IsSelected) sceneObject.RootChild.CreateSelected = true; sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); sceneObject.CreateScriptInstances(0, false, StateSource.PrimCrossing, UUID.Zero, false); sceneObject.RootChild.PhysActor.ForceSetVelocity(cAgent.Velocity); sceneObject.RootChild.PhysActor.Velocity = (cAgent.Velocity); sceneObject.AbsolutePosition = cAgent.Position; Animator.TrySetMovementAnimation(cAgent.SittingObjects.m_animation); m_nextSitAnimation = cAgent.SittingObjects.m_animation; cAgent.SittingObjects.m_objectID = sceneObject.UUID; m_objectToSitOn = cAgent.SittingObjects; foreach (ISceneChildEntity child in sceneObject.ChildrenEntities()) { foreach (TaskInventoryItem taskInv in child.Inventory.GetInventoryItems()) { foreach (ControllerData cd in cAgent.Controllers) { if (cd.ItemID == taskInv.ItemID || cd.ItemID == taskInv.OldItemID) { cd.ItemID = taskInv.ItemID; } } } } try { IScriptControllerModule m = RequestModuleInterface<IScriptControllerModule>(); if (m != null) if (cAgent.Controllers != null) m.Deserialize(cAgent.Controllers); } catch { } } } } } catch { } } catch (Exception ex) { MainConsole.Instance.Warn("[ScenePresence]: Error in CopyFrom: " + ex); } }
/// <summary> /// This is the event handler for client movement. If a client is moving, this event is triggering. /// </summary> public virtual void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { m_perfMonMS = Util.EnvironmentTickCount(); ++m_movementUpdateCount; if (m_movementUpdateCount < 1) m_movementUpdateCount = 1; #region Sanity Checking // This is irritating. Really. if (!AbsolutePosition.IsFinite()) { OutOfBoundsCall(Vector3.Zero); return; } #endregion Sanity Checking #region Inputs if (Frozen) return; //Do nothing, just end AgentManager.ControlFlags flags = (AgentManager.ControlFlags) agentData.ControlFlags; Quaternion bodyRotation = agentData.BodyRotation; //Check to see whether ray casting needs done // We multiply by 10 so that we don't trigger it when the camera moves slightly (as its 2 meter change) if (Util.GetFlatDistanceTo(agentData.CameraCenter, m_lastCameraCenter) > SIGNIFICANT_MOVEMENT*10) { m_lastCameraCenter = agentData.CameraCenter; Scene.AuroraEventManager.FireGenericEventHandler("SignficantCameraMovement", this); } // Camera location in world. We'll need to raytrace // from this location from time to time. m_CameraCenter = agentData.CameraCenter; // Use these three vectors to figure out what the agent is looking at // Convert it to a Matrix and/or Quaternion m_CameraAtAxis = agentData.CameraAtAxis; m_CameraLeftAxis = agentData.CameraLeftAxis; m_CameraUpAxis = agentData.CameraUpAxis; // The Agent's Draw distance setting DrawDistance = agentData.Far; // Check if Client has camera in 'follow cam' or 'build' mode. Vector3 camdif = (Vector3.One*m_bodyRot - Vector3.One*CameraRotation); m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)); m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; m_isAway = (flags & AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0; #endregion Inputs if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) { StandUp(); } //MainConsole.Instance.DebugFormat("[FollowCam]: {0}", m_followCamAuto); // Raycast from the avatar's head to the camera to see if there's anything blocking the view if ((m_movementUpdateCount%NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) { if (m_followCamAuto) { Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); } } if (!m_CameraCenter.IsFinite()) { m_CameraCenter = new Vector3(128, 128, 128); } IScriptControllerModule m = RequestModuleInterface<IScriptControllerModule>(); if (m != null) //Tell any scripts about it m.OnNewMovement(ref flags); if (m_autopilotMoving) CheckAtSitTarget(); // In the future, these values might need to go global. // Here's where you get them. if (!SitGround) SitGround = (flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0; m_AgentControlFlags = flags; m_headrotation = agentData.HeadRotation; m_state = agentData.State; PhysicsActor actor = PhysicsActor; if (actor == null) { //This happens while sitting, don't spam it //MainConsole.Instance.Debug("Null physical actor in AgentUpdate in " + m_scene.RegionInfo.RegionName); return; } bool update_movementflag = false; bool update_rotation = false; if (AllowMovement && !SitGround && !Frozen) { if (FallenStandUp) { //Poke the animator a bit Animator.UpdateMovementAnimations(false); m_bodyRot = bodyRotation; AddNewMovement(Vector3.Zero, bodyRotation); return; } if (agentData.UseClientAgentPosition) { m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; m_moveToPositionTarget = agentData.ClientAgentPosition; } int i = 0; bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; Quaternion q = bodyRotation; bool oldflying = PhysicsActor.Flying; if (m_forceFly) actor.Flying = true; else if (m_flyDisabled) actor.Flying = false; else if (actor.Flying != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)) actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); if (actor.Flying != oldflying) update_movementflag = true; if (q != m_bodyRot) { Quaternion delta = Quaternion.Inverse(m_bodyRot)*q; m_bodyRot = q; if (!(Math.Abs(delta.X) < 1e-5f && Math.Abs(delta.Y) < 1e-5f && Math.Abs(delta.Z) < 1e-5f)) update_rotation = true; } if (m_parentID == UUID.Zero) { bool bAllowUpdateMoveToPosition = false; bool bResetMoveToPosition = false; Vector3[] dirVectors; // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying // this prevents 'jumping' in inappropriate situations. if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying)) dirVectors = GetWalkDirectionVectors(); else dirVectors = Dir_Vectors; // The fact that m_movementflag is a byte needs to be fixed // it really should be a uint const uint nudgehack = 250; //Do these two like this to block out all others because it will slow it down if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) { bResetMoveToPosition = true; DCFlagKeyPressed = true; agent_control_v3 += dirVectors[8]; } else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) { bResetMoveToPosition = true; DCFlagKeyPressed = true; agent_control_v3 += dirVectors[9]; } else { foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint) flags & (uint) DCF) != 0) { bResetMoveToPosition = true; DCFlagKeyPressed = true; agent_control_v3 += dirVectors[i]; //MainConsole.Instance.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); if ((m_movementflag & (uint) DCF) == 0) { if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) { // m_movementflag |= (byte)nudgehack; m_movementflag |= nudgehack; } m_movementflag += (uint) DCF; update_movementflag = true; } } else { if ((m_movementflag & (uint) DCF) != 0 || ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((m_movementflag & nudgehack) == nudgehack)) ) // This or is for Nudge forward { m_movementflag -= ((uint) DCF); update_movementflag = true; /* if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((m_movementflag & (byte)nudgehack) == nudgehack)) { MainConsole.Instance.Debug("Removed Hack flag"); } */ } else { bAllowUpdateMoveToPosition = true; } } i++; } } //Paupaw:Do Proper PID for Autopilot here if (bResetMoveToPosition) { m_moveToPositionTarget = Vector3.Zero; m_moveToPositionInProgress = false; update_movementflag = true; bAllowUpdateMoveToPosition = false; } if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) { //Check the error term of the current position in relation to the target position if (Util.GetFlatDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) { // we are close enough to the target m_moveToPositionTarget = Vector3.Zero; m_moveToPositionInProgress = false; update_movementflag = true; } else { try { // move avatar in 2D at one meter/second towards target, in avatar coordinate frame. // This movement vector gets added to the velocity through AddNewMovement(). // Theoretically we might need a more complex PID approach here if other // unknown forces are acting on the avatar and we need to adaptively respond // to such forces, but the following simple approach seems to works fine. Vector3 LocalVectorToTarget3D = (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords // * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords *Quaternion.Inverse(bodyRotation); // mult by matix is faster but with creation, use *quarternion // Ignore z component of vector Vector3 LocalVectorToTarget2D; LocalVectorToTarget2D.X = LocalVectorToTarget3D.X; LocalVectorToTarget2D.Y = LocalVectorToTarget3D.Y; LocalVectorToTarget2D.Z = 0f; agent_control_v3 += LocalVectorToTarget2D; // update avatar movement flags. the avatar coordinate system is as follows: // // +X (forward) // // ^ // | // | // | // | // (left) +Y <--------o--------> -Y // avatar // | // | // | // | // v // -X // // based on the above avatar coordinate system, classify the movement into // one of left/right/back/forward. if (LocalVectorToTarget2D.Y > 0) //MoveLeft { m_movementflag += (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; //AgentControlFlags AgentControlFlags |= (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; update_movementflag = true; } else if (LocalVectorToTarget2D.Y < 0) //MoveRight { m_movementflag += (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; AgentControlFlags |= (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; update_movementflag = true; } if (LocalVectorToTarget2D.X < 0) //MoveBack { m_movementflag += (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; AgentControlFlags |= (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; update_movementflag = true; } else if (LocalVectorToTarget2D.X > 0) //Move Forward { m_movementflag += (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; AgentControlFlags |= (uint) Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; update_movementflag = true; } } catch (Exception e) { //Avoid system crash, can be slower but... MainConsole.Instance.DebugFormat("Crash! {0}", e); } } } } // Cause the avatar to stop flying if it's colliding // with something with the down arrow pressed. // Only do this if we're flying if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) { // Landing detection code // Are the landing controls requirements filled? bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); // Applies a satisfying roll effect to the avatar when flying. if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0) && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)) { ApplyFlyingRoll(FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0)); } else if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0) && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)) { ApplyFlyingRoll(-FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0)); } else { if (m_AngularVelocity.Z != 0) m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); } // Are the collision requirements fulfilled? bool colliding = (m_physicsActor.IsColliding == true); if (m_physicsActor.Flying && colliding && controlland) { // nesting this check because LengthSquared() is expensive and we don't // want to do it every step when flying. // then call it in the if... //The == Zero and Z > 0.1 are to stop people from flying and then falling down because the physics engine hasn't calculted the push yet if (Velocity != Vector3.Zero && Math.Abs(Velocity.Z) > 0.05 && (Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) { StopFlying(); SendTerseUpdateToAllClients(); } } } // If the agent update does move the avatar, then calculate the force ready for the velocity update, // which occurs later in the main scene loop if (update_movementflag || (update_rotation && DCFlagKeyPressed)) { // MainConsole.Instance.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed)); // MainConsole.Instance.DebugFormat( // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); AddNewMovement(agent_control_v3, q); } } if ((update_movementflag || update_rotation) && (m_parentID == UUID.Zero)) Animator.UpdateMovementAnimations(false); IAgentUpdateMonitor reporter = m_scene.RequestModuleInterface<IMonitorModule>().GetMonitor<IAgentUpdateMonitor>(Scene); if (reporter != null) reporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); }
/// <summary> /// This method determines the proper movement related animation /// </summary> private string DetermineMovementAnimation() { const float FALL_DELAY = 800f; const float PREJUMP_DELAY = 200f; const float JUMP_PERIOD = 800f; #region Inputs 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); // 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 heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_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; if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown) { heldTurnLeft = false; heldTurnRight = false; } // 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; } // Is the avatar trying to move? // bool moving = (move != Vector3.Zero); #endregion Inputs #region Flying if (actor != null && actor.Flying) { m_animTickFall = 0; m_animTickJump = 0; m_jumping = false; Falling = false; m_jumpVelocity = 0f; actor.Selected = false; m_fallHeight = actor.Position.Z; // save latest flying height if (move.X != 0f || move.Y != 0f) { return(m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); } else if (move.Z > 0f) { return("HOVER_UP"); } else if (move.Z < 0f) { if (actor != null && actor.IsColliding) { return("LAND"); } else { return("HOVER_DOWN"); } } else { return("HOVER"); } } #endregion Flying #region Falling/Floating/Landing if ((actor == null || !actor.IsColliding) && !m_jumping) { float fallElapsed = (float)(Environment.TickCount - m_animTickFall); float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; if (!m_jumping && (fallVelocity < -3.0f)) { Falling = true; } if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) { // not falling yet, or going up // reset start of fall time m_animTickFall = Environment.TickCount; } else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying)) { // Falling long enough to trigger the animation return("FALLDOWN"); } // Check if the user has stopped walking just now if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero)) { return("STAND"); } return(CurrentMovementAnimation); } #endregion Falling/Floating/Landing #region Jumping // section added for jumping... int jumptime; jumptime = Environment.TickCount - m_animTickJump; if ((move.Z > 0f) && (!m_jumping)) { // Start jumping, prejump m_animTickFall = 0; m_jumping = true; Falling = false; actor.Selected = true; // borrowed for jumping flag m_animTickJump = Environment.TickCount; m_jumpVelocity = 0.35f; return("PREJUMP"); } if (m_jumping) { if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) { // end jumping m_jumping = false; Falling = false; actor.Selected = false; // borrowed for jumping flag m_jumpVelocity = 0f; m_animTickFall = Environment.TickCount; return("LAND"); } else if (jumptime > JUMP_PERIOD) { // jump down m_jumpVelocity = 0f; return("JUMP"); } else if (jumptime > PREJUMP_DELAY) { // jump up m_jumping = true; m_jumpVelocity = 10f; return("JUMP"); } } #endregion Jumping #region Ground Movement if (CurrentMovementAnimation == "FALLDOWN") { Falling = false; m_animTickFall = Environment.TickCount; // TODO: SOFT_LAND support float fallHeight = m_fallHeight - actor.Position.Z; if (fallHeight > 15.0f) { return("STANDUP"); } else if (fallHeight > 8.0f) { return("SOFT_LAND"); } else { return("LAND"); } } else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) { int landElapsed = Environment.TickCount - m_animTickFall; int limit = 1000; if (CurrentMovementAnimation == "LAND") { limit = 350; } // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client if ((m_animTickFall != 0) && (landElapsed <= limit)) { return(CurrentMovementAnimation); } else { m_fallHeight = actor.Position.Z; // save latest flying height return("STAND"); } } // next section moved outside paren. and realigned for jumping if (move.X != 0f || move.Y != 0f) { m_fallHeight = actor.Position.Z; // save latest flying height Falling = false; // Walking / crouchwalking / running if (move.Z < 0f) { return("CROUCHWALK"); } else if (m_scenePresence.SetAlwaysRun) { return("RUN"); } else { return("WALK"); } } else if (!m_jumping) { Falling = false; // Not walking if (move.Z < 0) { return("CROUCH"); } else if (heldTurnLeft) { return("TURNLEFT"); } else if (heldTurnRight) { return("TURNRIGHT"); } else { return("STAND"); } } #endregion Ground Movement Falling = false; return(CurrentMovementAnimation); }
public void CopyFrom(AgentData cAgent) { m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; m_pos = cAgent.Position; m_velocity = cAgent.Velocity; m_CameraCenter = cAgent.Center; m_CameraAtAxis = cAgent.AtAxis; m_CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. // m_DrawDistance = cAgent.Far; m_DrawDistance = Scene.DefaultDrawDistance; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; m_bodyRot = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) m_godLevel = cAgent.GodLevel; m_setAlwaysRun = cAgent.AlwaysRun; m_appearance = new AvatarAppearance(cAgent.Appearance); if (m_physicsActor != null) { bool isFlying = m_physicsActor.Flying; RemoveFromPhysicalScene(); AddToPhysicalScene(isFlying); } /* uint i = 0; try { if (cAgent.Wearables == null) cAgent.Wearables = new UUID[0]; AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; for (uint n = 0; n < cAgent.Wearables.Length; n += 2) { UUID itemId = cAgent.Wearables[n]; UUID assetId = cAgent.Wearables[n + 1]; wears[i++] = new AvatarWearable(itemId, assetId); } // m_appearance.Wearables = wears; Primitive.TextureEntry textures = null; if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) textures = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); byte[] visuals = null; if ((cAgent.VisualParams != null) && (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) visuals = (byte[])cAgent.VisualParams.Clone(); m_appearance = new AvatarAppearance(cAgent.AgentID,wears,textures,visuals); } catch (Exception e) { m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); } // Attachments try { if (cAgent.Attachments != null) { m_appearance.ClearAttachments(); foreach (AvatarAttachment att in cAgent.Attachments) { m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); } } } catch { } */ try { lock (scriptedcontrols) { if (cAgent.Controllers != null) { scriptedcontrols.Clear(); foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; scriptedcontrols[sc.itemID] = sc; } } } } catch { } // Animations try { Animator.ResetAnimations(); Animator.Animations.FromArray(cAgent.Anims); } catch { } //cAgent.GroupID = ?? //Groups??? }
/// <summary> /// This method determines the proper movement related animation /// </summary> private string DetermineMovementAnimation() { const int FALL_DELAY = 800; const int PREJUMP_DELAY = 200; const int JUMP_PERIOD = 800; #region Inputs if (m_scenePresence.IsInTransit) { return(CurrentMovementAnimation); } if (m_scenePresence.SitGround) { currentControlState = motionControlStates.sitted; return("SITGROUND"); } if (m_scenePresence.ParentID != 0 || m_scenePresence.ParentUUID != UUID.Zero) { currentControlState = motionControlStates.sitted; return("SIT"); } AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; PhysicsActor actor = m_scenePresence.PhysicsActor; const AgentManager.ControlFlags ANYXYMASK = ( AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG ); // Check control flags /* not in use * bool heldForward = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)) != 0); * bool heldBack = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG)) != 0); * bool heldLeft = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS)) != 0); * bool heldRight = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG)) != 0); */ 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_NUDGE_UP_POS)) != 0); // excluded nudge up so it doesn't trigger jump state bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS)) != 0); bool heldDown = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG)) != 0); //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; bool heldOnXY = ((controlFlags & ANYXYMASK) != 0); if (heldOnXY || heldUp || heldDown) { heldTurnLeft = false; heldTurnRight = false; } #endregion Inputs // no physics actor case if (actor == null) { // well what to do? currentControlState = motionControlStates.onsurface; if (heldOnXY) { return("WALK"); } return("STAND"); } #region Flying bool isColliding = actor.IsColliding; if (actor.Flying) { m_animTickFall = 0; m_animTickJump = 0; m_jumping = false; Falling = false; currentControlState = motionControlStates.flying; if (heldOnXY) { return(m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); } else if (heldUp) { return("HOVER_UP"); } else if (heldDown) { if (isColliding) { actor.Flying = false; currentControlState = motionControlStates.landing; m_animTickLand = Environment.TickCount; return("LAND"); } else { return("HOVER_DOWN"); } } else { return("HOVER"); } } else { if (isColliding && currentControlState == motionControlStates.flying) { currentControlState = motionControlStates.landing; m_animTickLand = Environment.TickCount; return("LAND"); } } #endregion Flying #region Falling/Floating/Landing if (!isColliding && currentControlState != motionControlStates.jumping) { float fallVelocity = actor.Velocity.Z; // if stable on Hover assume falling if (actor.PIDHoverActive && fallVelocity < 0.05f) { Falling = true; currentControlState = motionControlStates.falling; m_lastFallVelocity = fallVelocity; return("FALLDOWN"); } if (fallVelocity < -2.5f) { Falling = true; } if (m_animTickFall == 0 || (fallVelocity >= -0.5f)) { m_animTickFall = Environment.TickCount; } else { int fallElapsed = (Environment.TickCount - m_animTickFall); if ((fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f)) { currentControlState = motionControlStates.falling; m_lastFallVelocity = fallVelocity; // Falling long enough to trigger the animation return("FALLDOWN"); } } // Check if the user has stopped walking just now if (CurrentMovementAnimation == "WALK" && !heldOnXY && !heldDown && !heldUp) { return("STAND"); } return(CurrentMovementAnimation); } m_animTickFall = 0; #endregion Falling/Floating/Landing #region Jumping // section added for jumping... if (isColliding && heldUp && currentControlState != motionControlStates.jumping && !actor.PIDHoverActive) { // Start jumping, prejump currentControlState = motionControlStates.jumping; m_jumping = true; Falling = false; m_animTickJump = Environment.TickCount; return("PREJUMP"); } if (currentControlState == motionControlStates.jumping) { int jumptime = Environment.TickCount - m_animTickJump; if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) { // end jumping m_jumping = false; Falling = false; actor.Selected = false; // borrowed for jumping flag m_animTickLand = Environment.TickCount; currentControlState = motionControlStates.landing; return("LAND"); } else if (jumptime > JUMP_PERIOD) { // jump down return("JUMP"); } else if (jumptime > PREJUMP_DELAY) { // jump up m_jumping = true; return("JUMP"); } return(CurrentMovementAnimation); } #endregion Jumping #region Ground Movement if (currentControlState == motionControlStates.falling) { Falling = false; currentControlState = motionControlStates.landing; m_animTickLand = Environment.TickCount; // TODO: SOFT_LAND support float fallVsq = m_lastFallVelocity * m_lastFallVelocity; if (fallVsq > 300f) // aprox 20*h { return("STANDUP"); } else if (fallVsq > 160f) { return("SOFT_LAND"); } else { return("LAND"); } } if (currentControlState == motionControlStates.landing) { Falling = false; int landElapsed = Environment.TickCount - m_animTickLand; int limit = 1000; if (CurrentMovementAnimation == "LAND") { limit = 350; } // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client if ((m_animTickLand != 0) && (landElapsed <= limit)) { return(CurrentMovementAnimation); } else { currentControlState = motionControlStates.onsurface; m_animTickLand = 0; return("STAND"); } } // next section moved outside paren. and realigned for jumping if (heldOnXY) { currentControlState = motionControlStates.onsurface; Falling = false; // Walking / crouchwalking / running if (heldDown) { return("CROUCHWALK"); } // We need to prevent these animations if the user tries to make their avatar walk or run whilst // specifying AGENT_CONTROL_STOP (pressing down space on viewers). else if (!m_scenePresence.AgentControlStopActive) { if (m_scenePresence.SetAlwaysRun) { return("RUN"); } else { return("WALK"); } } } else { currentControlState = motionControlStates.onsurface; Falling = false; // Not walking if (heldDown) { return("CROUCH"); } else if (heldTurnLeft) { return("TURNLEFT"); } else if (heldTurnRight) { return("TURNRIGHT"); } else { return("STAND"); } } #endregion Ground Movement return(CurrentMovementAnimation); }
public void CopyFrom(AgentData cAgent) { try { m_callbackURI = cAgent.CallbackURI; m_pos = cAgent.Position; Velocity = cAgent.Velocity; m_CameraCenter = cAgent.Center; //m_avHeight = cAgent.Size.Z; m_CameraAtAxis = cAgent.AtAxis; m_CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; DrawDistance = cAgent.Far; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; m_bodyRot = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; //if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) // m_godLevel = cAgent.GodLevel; m_speedModifier = cAgent.Speed; DrawDistance = cAgent.DrawDistance; m_setAlwaysRun = cAgent.AlwaysRun; IAvatarAppearanceModule appearance = RequestModuleInterface<IAvatarAppearanceModule> (); if (appearance != null) { appearance.InitialHasWearablesBeenSent = cAgent.SentInitialWearables; appearance.Appearance = new AvatarAppearance (cAgent.Appearance); } try { IScriptControllerModule m = RequestModuleInterface<IScriptControllerModule> (); if (m != null) if (cAgent.Controllers != null) m.Deserialize(cAgent.Controllers); } catch { } // Animations try { Animator.ResetAnimations(); Animator.Animations.FromArray(cAgent.Anims); } catch { } } catch(Exception ex) { m_log.Warn("[ScenePresence]: Error in CopyFrom: " + ex.ToString()); } }
public void CopyFrom(AgentData cAgent) { try { m_callbackURI = cAgent.CallbackURI; m_pos = cAgent.Position; Velocity = cAgent.Velocity; m_CameraCenter = cAgent.Center; SetHeight (cAgent.Size.Z); m_CameraAtAxis = cAgent.AtAxis; m_CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; DrawDistance = cAgent.Far; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; m_bodyRot = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; m_savedVelocity = cAgent.Velocity; SpeedModifier = cAgent.Speed; DrawDistance = cAgent.DrawDistance; m_setAlwaysRun = cAgent.AlwaysRun; if(cAgent.IsCrossing) ((Scene)m_scene).AuthenticateHandler.GetAgentCircuitData (UUID).teleportFlags |= (uint)OpenMetaverse.TeleportFlags.ViaRegionID; IAvatarAppearanceModule appearance = RequestModuleInterface<IAvatarAppearanceModule> (); if (appearance != null) { appearance.InitialHasWearablesBeenSent = cAgent.SentInitialWearables; appearance.Appearance = new AvatarAppearance (cAgent.Appearance); } try { IScriptControllerModule m = RequestModuleInterface<IScriptControllerModule> (); if (m != null) if (cAgent.Controllers != null) m.Deserialize(cAgent.Controllers); } catch { } // Animations try { Animator.ResetAnimations(); Animator.Animations.FromArray(cAgent.Anims); } catch { } } catch(Exception ex) { m_log.Warn("[ScenePresence]: Error in CopyFrom: " + ex.ToString()); } }
/// <summary> /// This is the event handler for client movement. If a client is moving, this event is triggering. /// </summary> public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { //if (m_isChildAgent) //{ // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); // return; //} m_perfMonMS = Util.EnvironmentTickCount(); ++m_movementUpdateCount; if (m_movementUpdateCount < 1) m_movementUpdateCount = 1; #region Sanity Checking // This is irritating. Really. if (!AbsolutePosition.IsFinite()) { RemoveFromPhysicalScene(); m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); m_pos = m_LastFinitePos; if (!m_pos.IsFinite()) { m_pos.X = 127f; m_pos.Y = 127f; m_pos.Z = 127f; m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); } AddToPhysicalScene(false); } else { m_LastFinitePos = m_pos; } #endregion Sanity Checking #region Inputs AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; Quaternion bodyRotation = agentData.BodyRotation; // Camera location in world. We'll need to raytrace // from this location from time to time. m_CameraCenter = agentData.CameraCenter; if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance) { ReprioritizeUpdates(); m_lastCameraCenter = m_CameraCenter; } // Use these three vectors to figure out what the agent is looking at // Convert it to a Matrix and/or Quaternion m_CameraAtAxis = agentData.CameraAtAxis; m_CameraLeftAxis = agentData.CameraLeftAxis; m_CameraUpAxis = agentData.CameraUpAxis; // The Agent's Draw distance setting // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. // m_DrawDistance = agentData.Far; m_DrawDistance = Scene.DefaultDrawDistance; // Check if Client has camera in 'follow cam' or 'build' mode. Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; #endregion Inputs if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) { StandUp(); } //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); // Raycast from the avatar's head to the camera to see if there's anything blocking the view if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) { if (m_followCamAuto) { Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); } } lock (scriptedcontrols) { if (scriptedcontrols.Count > 0) { SendControlToScripts((uint)flags); flags = RemoveIgnoredControls(flags, IgnoredControls); } } if (m_autopilotMoving) CheckAtSitTarget(); if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) { // TODO: This doesn't prevent the user from walking yet. // Setting parent ID would fix this, if we knew what value // to use. Or we could add a m_isSitting variable. //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); SitGround = true; } // In the future, these values might need to go global. // Here's where you get them. m_AgentControlFlags = flags; m_headrotation = agentData.HeadRotation; m_state = agentData.State; PhysicsActor actor = PhysicsActor; if (actor == null) { return; } if (m_allowMovement && !SitGround) { bool update_movementflag = false; if (agentData.UseClientAgentPosition) { MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; MoveToPositionTarget = agentData.ClientAgentPosition; } int i = 0; bool update_rotation = false; bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; Quaternion q = bodyRotation; bool oldflying = PhysicsActor.Flying; if (m_forceFly) actor.Flying = true; else if (m_flyDisabled) actor.Flying = false; else actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); if (actor.Flying != oldflying) update_movementflag = true; if (q != m_bodyRot) { m_bodyRot = q; update_rotation = true; } if (m_parentID == 0) { bool bAllowUpdateMoveToPosition = false; Vector3[] dirVectors; // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying // this prevents 'jumping' in inappropriate situations. if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying)) dirVectors = GetWalkDirectionVectors(); else dirVectors = Dir_Vectors; // The fact that m_movementflag is a byte needs to be fixed // it really should be a uint // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. uint nudgehack = 250; foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint)flags & (uint)DCF) != 0) { DCFlagKeyPressed = true; try { agent_control_v3 += dirVectors[i]; //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); } catch (IndexOutOfRangeException) { // Why did I get this? } if ((m_movementflag & (byte)(uint)DCF) == 0) { if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) { m_movementflag |= (byte)nudgehack; } m_movementflag += (byte)(uint)DCF; update_movementflag = true; } } else { if ((m_movementflag & (byte)(uint)DCF) != 0 || ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((m_movementflag & (byte)nudgehack) == nudgehack)) ) // This or is for Nudge forward { m_movementflag -= ((byte)(uint)DCF); update_movementflag = true; /* if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((m_movementflag & (byte)nudgehack) == nudgehack)) { m_log.Debug("Removed Hack flag"); } */ } else { bAllowUpdateMoveToPosition = true; } } i++; } if (MovingToTarget) { // If the user has pressed a key then we want to cancel any move to target. if (DCFlagKeyPressed) { ResetMoveToTarget(); update_movementflag = true; } else if (bAllowUpdateMoveToPosition) { if (HandleMoveToTargetUpdate(ref agent_control_v3, bodyRotation)) update_movementflag = true; } } } // Cause the avatar to stop flying if it's colliding // with something with the down arrow pressed. // Only do this if we're flying if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) { // Landing detection code // Are the landing controls requirements filled? bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); // Are the collision requirements fulfilled? bool colliding = (m_physicsActor.IsColliding == true); if (m_physicsActor.Flying && colliding && controlland) { // nesting this check because LengthSquared() is expensive and we don't // want to do it every step when flying. if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) StopFlying(); } } // If the agent update does move the avatar, then calculate the force ready for the velocity update, // which occurs later in the main scene loop if (update_movementflag || (update_rotation && DCFlagKeyPressed)) { // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed)); // m_log.DebugFormat( // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); AddNewMovement(agent_control_v3, q); } if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) Animator.UpdateMovementAnimations(); } m_scene.EventManager.TriggerOnClientMovement(this); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); }
/// <summary> /// This method determines the proper movement related animation /// </summary> 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"); } AgentManager.ControlFlags 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; // 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 && move.Z == 0 && fallVelocity == 0.0f && !heldUp && !heldDown && move.CompareTo(Vector3.Zero) == 0) { return("TURNLEFT"); } if (heldTurnRight && yawNeg && !heldForward && !heldBack && actor != null && !actor.IsJumping && !actor.Flying && move.Z == 0 && fallVelocity == 0.0f && !heldUp && !heldDown && move.CompareTo(Vector3.Zero) == 0) { return("TURNRIGHT"); } #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"); } else if (standupElapsed < BRUSH_TIME && m_useSplatAnimation) { m_scenePresence.FallenStandUp = true; return("BRUSH"); } else if (m_animTickStandup != 0 || 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 (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) { 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"); } else { 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"); } else { return("HOVER_DOWN"); } } 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 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 || m_animTickWalk == 0))//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 (m_animTickFall == 0) { m_animTickFall = Util.EnvironmentTickCount(); } return("FALLDOWN"); } #endregion Falling/Floating/Landing #region Ground Movement if (m_movementAnimation == "FALLDOWN") { float fallElapsed = (Util.EnvironmentTickCount() - m_animTickFall) / 1000f; if (fallElapsed < 0.75) { m_animTickFall = Util.EnvironmentTickCount(); return("SOFT_LAND"); } else if (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"); } else { if (m_useSplatAnimation) { m_animTickStandup = Util.EnvironmentTickCount(); return("STANDUP"); } else { return("LAND"); } } } else if (m_movementAnimation == "LAND") { if (actor != null && actor.Velocity.Z < 0) { if (actor.Velocity.Z < SOFTLAND_FORCE) { return("LAND"); } return("SOFT_LAND"); } } m_animTickFall = 0; if (move.Z <= 0f) { if (actor != null && (move.X != 0f || move.Y != 0f || actor.Velocity.X != 0 && actor.Velocity.Y != 0)) { wasLastFlying = false; if (actor.IsColliding) { m_animTickWalk = Util.EnvironmentTickCount(); } // 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 && !wasLastFlying) { return("CROUCH"); } else { return("STAND"); } } } #endregion Ground Movement return(m_movementAnimation); }
private void CopyFrom(AgentData cAgent) { m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; m_pos = cAgent.Position; m_velocity = cAgent.Velocity; CameraPosition = cAgent.Center; CameraAtAxis = cAgent.AtAxis; CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. // DrawDistance = cAgent.Far; DrawDistance = Scene.DefaultDrawDistance; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; Rotation = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) GodLevel = cAgent.GodLevel; SetAlwaysRun = cAgent.AlwaysRun; Appearance = new AvatarAppearance(cAgent.Appearance); if (PhysicsActor != null) { bool isFlying = Flying; RemoveFromPhysicalScene(); AddToPhysicalScene(isFlying); } try { lock (scriptedcontrols) { if (cAgent.Controllers != null) { scriptedcontrols.Clear(); foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; scriptedcontrols[sc.itemID] = sc; } } } } catch { } // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.Anims != null) Animator.Animations.FromArray(cAgent.Anims); if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0) { m_attachments = new List<SceneObjectGroup>(); int i = 0; foreach (ISceneObject so in cAgent.AttachmentObjects) { ((SceneObjectGroup)so).LocalId = 0; ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); so.SetState(cAgent.AttachmentObjectStates[i++], m_scene); m_scene.IncomingCreateObject(so); } } }
public virtual void InTransit() { m_inTransit = true; if ((m_physicsActor != null) && m_physicsActor.Flying) m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY; else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY; }
/// <summary> /// This is the event handler for client movement. If a client is moving, this event is triggering. /// </summary> public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { //m_log.DebugFormat( // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); if (IsChildAgent) { // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); return; } #region Sanity Checking // This is irritating. Really. if (!AbsolutePosition.IsFinite()) { RemoveFromPhysicalScene(); m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); m_pos = m_LastFinitePos; if (!m_pos.IsFinite()) { m_pos.X = 127f; m_pos.Y = 127f; m_pos.Z = 127f; m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); } AddToPhysicalScene(false); } else { m_LastFinitePos = m_pos; } #endregion Sanity Checking #region Inputs AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; // The Agent's Draw distance setting // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. // DrawDistance = agentData.Far; DrawDistance = Scene.DefaultDrawDistance; m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; #endregion Inputs // // Make anims work for client side autopilot // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0) // m_updateCount = UPDATE_COUNT; // // // Make turning in place work // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 || // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) // m_updateCount = UPDATE_COUNT; if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) { StandUp(); } uint flagsForScripts = (uint)flags; flags = RemoveIgnoredControls(flags, IgnoredControls); if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) HandleAgentSitOnGround(); // In the future, these values might need to go global. // Here's where you get them. m_AgentControlFlags = flags; m_headrotation = agentData.HeadRotation; byte oldState = State; State = agentData.State; // We need to send this back to the client in order to stop the edit beams if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) ControllingClient.SendAgentTerseUpdate(this); PhysicsActor actor = PhysicsActor; if (actor == null) { SendControlsToScripts(flagsForScripts); return; } if (AllowMovement && !SitGround) { Quaternion bodyRotation = agentData.BodyRotation; bool update_rotation = false; if (bodyRotation != Rotation) { Rotation = bodyRotation; update_rotation = true; } bool update_movementflag = false; if (agentData.UseClientAgentPosition) { MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; MoveToPositionTarget = agentData.ClientAgentPosition; } int i = 0; bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; bool newFlying = actor.Flying; if (ForceFly) newFlying = true; else if (FlyDisabled) newFlying = false; else newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); if (actor.Flying != newFlying) { // Note: ScenePresence.Flying is actually fetched from the physical actor // so setting PhysActor.Flying here also sets the ScenePresence's value. actor.Flying = newFlying; update_movementflag = true; } if (ParentID == 0) { bool bAllowUpdateMoveToPosition = false; Vector3[] dirVectors; // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying // this prevents 'jumping' in inappropriate situations. if (!Flying && (m_mouseLook || m_leftButtonDown)) dirVectors = GetWalkDirectionVectors(); else dirVectors = Dir_Vectors; // The fact that MovementFlag is a byte needs to be fixed // it really should be a uint // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. uint nudgehack = 250; foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint)flags & (uint)DCF) != 0) { DCFlagKeyPressed = true; try { agent_control_v3 += dirVectors[i]; //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); } catch (IndexOutOfRangeException) { // Why did I get this? } if ((MovementFlag & (byte)(uint)DCF) == 0) { if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) { MovementFlag |= (byte)nudgehack; } //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); MovementFlag += (byte)(uint)DCF; update_movementflag = true; } } else { if ((MovementFlag & (byte)(uint)DCF) != 0 || ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) && ((MovementFlag & (byte)nudgehack) == nudgehack)) ) // This or is for Nudge forward { //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); MovementFlag -= ((byte)(uint)DCF); update_movementflag = true; /* if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((MovementFlag & (byte)nudgehack) == nudgehack)) { m_log.Debug("Removed Hack flag"); } */ } else { bAllowUpdateMoveToPosition = true; } } i++; } if (MovingToTarget) { // If the user has pressed a key then we want to cancel any move to target. if (DCFlagKeyPressed) { ResetMoveToTarget(); update_movementflag = true; } else if (bAllowUpdateMoveToPosition) { // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a // certain position. It's only check for tolerance on returning to that position is 0.2 // rather than 1, at which point it removes its force target. if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3)) update_movementflag = true; } } } // Cause the avatar to stop flying if it's colliding // with something with the down arrow pressed. // Only do this if we're flying if (Flying && !ForceFly) { // Landing detection code // Are the landing controls requirements filled? bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); //m_log.Debug("[CONTROL]: " +flags); // Applies a satisfying roll effect to the avatar when flying. if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) { ApplyFlyingRoll( FLY_ROLL_RADIANS_PER_UPDATE, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); } else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) { ApplyFlyingRoll( -FLY_ROLL_RADIANS_PER_UPDATE, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); } else { if (m_AngularVelocity.Z != 0) m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); } if (Flying && IsColliding && controlland) { // nesting this check because LengthSquared() is expensive and we don't // want to do it every step when flying. if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) StopFlying(); } } // If the agent update does move the avatar, then calculate the force ready for the velocity update, // which occurs later in the main scene loop if (update_movementflag || (update_rotation && DCFlagKeyPressed)) { // m_log.DebugFormat( // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", // m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); AddNewMovement(agent_control_v3); } // else // { // if (!update_movementflag) // { // m_log.DebugFormat( // "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false", // m_scene.RegionInfo.RegionName, agent_control_v3, Name); // } // } if (update_movementflag && ParentID == 0) Animator.UpdateMovementAnimations(); SendControlsToScripts(flagsForScripts); } // We need to send this back to the client in order to see the edit beams if ((State & (uint)AgentState.Editing) != 0) ControllingClient.SendAgentTerseUpdate(this); m_scene.EventManager.TriggerOnClientMovement(this); }
/// <summary> /// This is the event handler for client movement. If a client is moving, this event is triggering. /// </summary> public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { // m_log.DebugFormat( // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); if (IsChildAgent) { // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); return; } ++m_movementUpdateCount; if (m_movementUpdateCount < 1) m_movementUpdateCount = 1; #region Sanity Checking // This is irritating. Really. if (!AbsolutePosition.IsFinite()) { RemoveFromPhysicalScene(); m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); m_pos = m_LastFinitePos; if (!m_pos.IsFinite()) { m_pos.X = 127f; m_pos.Y = 127f; m_pos.Z = 127f; m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); } AddToPhysicalScene(false); } else { m_LastFinitePos = m_pos; } #endregion Sanity Checking #region Inputs AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; // Camera location in world. We'll need to raytrace // from this location from time to time. CameraPosition = agentData.CameraCenter; if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) { ReprioritizeUpdates(); m_lastCameraPosition = CameraPosition; } // Use these three vectors to figure out what the agent is looking at // Convert it to a Matrix and/or Quaternion CameraAtAxis = agentData.CameraAtAxis; CameraLeftAxis = agentData.CameraLeftAxis; CameraUpAxis = agentData.CameraUpAxis; // The Agent's Draw distance setting // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. // DrawDistance = agentData.Far; DrawDistance = Scene.DefaultDrawDistance; // Check if Client has camera in 'follow cam' or 'build' mode. Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f) && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; #endregion Inputs // // Make anims work for client side autopilot // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0) // m_updateCount = UPDATE_COUNT; // // // Make turning in place work // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 || // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) // m_updateCount = UPDATE_COUNT; if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) { StandUp(); } //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); // Raycast from the avatar's head to the camera to see if there's anything blocking the view if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) { if (m_followCamAuto) { Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); } } uint flagsForScripts = (uint)flags; flags = RemoveIgnoredControls(flags, IgnoredControls); if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) HandleAgentSitOnGround(); // In the future, these values might need to go global. // Here's where you get them. m_AgentControlFlags = flags; m_headrotation = agentData.HeadRotation; State = agentData.State; PhysicsActor actor = PhysicsActor; if (actor == null) { SendControlsToScripts(flagsForScripts); return; } if (AllowMovement && !SitGround) { Quaternion bodyRotation = agentData.BodyRotation; bool update_rotation = false; if (bodyRotation != Rotation) { Rotation = bodyRotation; update_rotation = true; } bool update_movementflag = false; if (agentData.UseClientAgentPosition) { MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; MoveToPositionTarget = agentData.ClientAgentPosition; } int i = 0; bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; bool newFlying = actor.Flying; if (ForceFly) newFlying = true; else if (FlyDisabled) newFlying = false; else newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); if (actor.Flying != newFlying) { // Note: ScenePresence.Flying is actually fetched from the physical actor // so setting PhysActor.Flying here also sets the ScenePresence's value. actor.Flying = newFlying; update_movementflag = true; } if (ParentID == 0) { bool bAllowUpdateMoveToPosition = false; Vector3[] dirVectors; // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying // this prevents 'jumping' in inappropriate situations. if (!Flying && (m_mouseLook || m_leftButtonDown)) dirVectors = GetWalkDirectionVectors(); else dirVectors = Dir_Vectors; // The fact that MovementFlag is a byte needs to be fixed // it really should be a uint // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. uint nudgehack = 250; foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint)flags & (uint)DCF) != 0) { DCFlagKeyPressed = true; try { agent_control_v3 += dirVectors[i]; //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); } catch (IndexOutOfRangeException) { // Why did I get this? } if ((MovementFlag & (byte)(uint)DCF) == 0) { if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) { MovementFlag |= (byte)nudgehack; } //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); MovementFlag += (byte)(uint)DCF; update_movementflag = true; } } else { if ((MovementFlag & (byte)(uint)DCF) != 0 || ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) && ((MovementFlag & (byte)nudgehack) == nudgehack)) ) // This or is for Nudge forward { //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); MovementFlag -= ((byte)(uint)DCF); update_movementflag = true; /* if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((MovementFlag & (byte)nudgehack) == nudgehack)) { m_log.Debug("Removed Hack flag"); } */ } else { bAllowUpdateMoveToPosition = true; } } i++; } if (MovingToTarget) { // If the user has pressed a key then we want to cancel any move to target. if (DCFlagKeyPressed) { ResetMoveToTarget(); update_movementflag = true; } else if (bAllowUpdateMoveToPosition) { // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a // certain position. It's only check for tolerance on returning to that position is 0.2 // rather than 1, at which point it removes its force target. if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3)) update_movementflag = true; } } } // Cause the avatar to stop flying if it's colliding // with something with the down arrow pressed. // Only do this if we're flying if (Flying && !ForceFly) { // Landing detection code // Are the landing controls requirements filled? bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); if (Flying && IsColliding && controlland) { // nesting this check because LengthSquared() is expensive and we don't // want to do it every step when flying. if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) StopFlying(); } } // If the agent update does move the avatar, then calculate the force ready for the velocity update, // which occurs later in the main scene loop if (update_movementflag || (update_rotation && DCFlagKeyPressed)) { // m_log.DebugFormat( // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", // m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); AddNewMovement(agent_control_v3); } // else // { // if (!update_movementflag) // { // m_log.DebugFormat( // "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false", // m_scene.RegionInfo.RegionName, agent_control_v3, Name); // } // } if (update_movementflag && ParentID == 0) Animator.UpdateMovementAnimations(); SendControlsToScripts(flagsForScripts); } m_scene.EventManager.TriggerOnClientMovement(this); TriggerScenePresenceUpdated(); }
private void CopyFrom(AgentData cAgent) { m_callbackURI = cAgent.CallbackURI; // m_log.DebugFormat( // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", // Name, m_scene.RegionInfo.RegionName, m_callbackURI); m_pos = cAgent.Position; m_velocity = cAgent.Velocity; CameraPosition = cAgent.Center; CameraAtAxis = cAgent.AtAxis; CameraLeftAxis = cAgent.LeftAxis; CameraUpAxis = cAgent.UpAxis; ParentUUID = cAgent.ParentPart; PrevSitOffset = cAgent.SitOffset; // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. DrawDistance = cAgent.Far; // DrawDistance = Scene.DefaultDrawDistance; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; Rotation = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) GodLevel = cAgent.GodLevel; SetAlwaysRun = cAgent.AlwaysRun; Appearance = new AvatarAppearance(cAgent.Appearance); if (PhysicsActor != null) { bool isFlying = Flying; RemoveFromPhysicalScene(); AddToPhysicalScene(isFlying); } try { lock (scriptedcontrols) { if (cAgent.Controllers != null) { scriptedcontrols.Clear(); foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); sc.objectID = c.ObjectID; sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; scriptedcontrols[sc.itemID] = sc; } } } } catch { } // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.Anims != null) Animator.Animations.FromArray(cAgent.Anims); if (cAgent.DefaultAnim != null) Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); if (cAgent.AnimState != null) Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); if (Scene.AttachmentsModule != null) { // If the JobEngine is running we can schedule this job now and continue rather than waiting for all // attachments to copy, which might take a long time in the Hypergrid case as the entire inventory // graph is inspected for each attachments and assets possibly fetched. // // We don't need to worry about a race condition as the job to later start the scripts is also // JobEngine scheduled and so will always occur after this task. // XXX: This will not be true if JobEngine ever gets more than one thread. WorkManager.RunJob( "CopyAttachments", o => Scene.AttachmentsModule.CopyAttachments(cAgent, this), null, string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name), true); } // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart // script attachments can outrace this thread. lock (m_originRegionIDAccessLock) m_originRegionID = cAgent.RegionID; }
/// <summary> /// This is the event handler for client movement. If a client is moving, this event is triggering. /// </summary> public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { // m_log.DebugFormat( // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", // Scene.Name, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); if (IsChildAgent) { // m_log.DebugFormat("DEBUG: HandleAgentUpdate: child agent in {0}", Scene.Name); return; } if (IsInTransit) return; #region Sanity Checking // This is irritating. Really. if (!AbsolutePosition.IsFinite()) { RemoveFromPhysicalScene(); m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); m_pos = m_LastFinitePos; if (!m_pos.IsFinite()) { m_pos.X = 127f; m_pos.Y = 127f; m_pos.Z = 127f; m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); } AddToPhysicalScene(false); } else { m_LastFinitePos = m_pos; } #endregion Sanity Checking #region Inputs AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; // The Agent's Draw distance setting // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the // region's draw distance. DrawDistance = agentData.Far; m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button // is first pressed, not whilst it is held down. If this is required in the future then need to look // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not // received (e.g. on holding LMB down on the avatar in a viewer). m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; #endregion Inputs // // Make anims work for client side autopilot // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0) // m_updateCount = UPDATE_COUNT; // // // Make turning in place work // if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 || // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) // m_updateCount = UPDATE_COUNT; if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) { StandUp(); } // Raycast from the avatar's head to the camera to see if there's anything blocking the view // this exclude checks may not be complete if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast()) { if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0) { Vector3 posAdjusted = AbsolutePosition; // posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f; posAdjusted.Z += 1.0f; // viewer current camera focus point Vector3 tocam = CameraPosition - posAdjusted; tocam.X = (float)Math.Round(tocam.X, 1); tocam.Y = (float)Math.Round(tocam.Y, 1); tocam.Z = (float)Math.Round(tocam.Z, 1); float distTocamlen = tocam.Length(); if (distTocamlen > 0.3f) { tocam *= (1.0f / distTocamlen); posAdjusted.X = (float)Math.Round(posAdjusted.X, 1); posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1); posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1); m_doingCamRayCast = true; m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback); } } else if (CameraConstraintActive && (m_mouseLook || ParentID != 0)) { Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right... UpdateCameraCollisionPlane(plane); CameraConstraintActive = false; } } uint flagsForScripts = (uint)flags; flags = RemoveIgnoredControls(flags, IgnoredControls); if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) HandleAgentSitOnGround(); // In the future, these values might need to go global. // Here's where you get them. m_AgentControlFlags = flags; m_headrotation = agentData.HeadRotation; byte oldState = State; State = agentData.State; // We need to send this back to the client in order to stop the edit beams if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) SendAgentTerseUpdate(this); PhysicsActor actor = PhysicsActor; // This will be the case if the agent is sitting on the groudn or on an object. if (actor == null) { SendControlsToScripts(flagsForScripts); return; } if (AllowMovement && !SitGround) { // m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); bool update_rotation = false; if (agentData.BodyRotation != Rotation) { Rotation = agentData.BodyRotation; update_rotation = true; } bool update_movementflag = false; if (agentData.UseClientAgentPosition) { MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; MoveToPositionTarget = agentData.ClientAgentPosition; } int i = 0; bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; bool newFlying = false; if (ForceFly) newFlying = true; else if (FlyDisabled) newFlying = false; else newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); if (actor.Flying != newFlying) { // Note: ScenePresence.Flying is actually fetched from the physical actor // so setting PhysActor.Flying here also sets the ScenePresence's value. actor.Flying = newFlying; update_movementflag = true; } if (ParentID == 0) { bool bAllowUpdateMoveToPosition = false; Vector3[] dirVectors; // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying // this prevents 'jumping' in inappropriate situations. // if (!Flying && (m_mouseLook || m_leftButtonDown)) // dirVectors = GetWalkDirectionVectors(); // else dirVectors = Dir_Vectors; // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint)flags & (uint)DCF) != 0) { DCFlagKeyPressed = true; try { agent_control_v3 += Dir_Vectors[i]; //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); } catch (IndexOutOfRangeException) { // Why did I get this? } if (((MovementFlag & (uint)DCF) == 0)) { //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); MovementFlag |= (uint)DCF; update_movementflag = true; } } else { if ((MovementFlag & (uint)DCF) != 0) { //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); MovementFlag &= (uint)~DCF; update_movementflag = true; /* if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((MovementFlag & (byte)nudgehack) == nudgehack)) { m_log.Debug("Removed Hack flag"); } */ } else { bAllowUpdateMoveToPosition = true; } } i++; } // Detect AGENT_CONTROL_STOP state changes if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0)) { AgentControlStopActive = !AgentControlStopActive; update_movementflag = true; } if (MovingToTarget) { // If the user has pressed a key then we want to cancel any move to target. if (DCFlagKeyPressed) { ResetMoveToTarget(); update_movementflag = true; } else if (bAllowUpdateMoveToPosition) { // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a // certain position. It's only check for tolerance on returning to that position is 0.2 // rather than 1, at which point it removes its force target. if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3)) update_movementflag = true; } } } // Cause the avatar to stop flying if it's colliding // with something with the down arrow pressed. // Only do this if we're flying if (Flying && !ForceFly) { // Need to stop in mid air if user holds down AGENT_CONTROL_STOP // if (AgentControlStopActive) // { // agent_control_v3 = Vector3.Zero; // } // else { // Landing detection code // Are the landing controls requirements filled? bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); //m_log.Debug("[CONTROL]: " +flags); // Applies a satisfying roll effect to the avatar when flying. if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) { ApplyFlyingRoll( FLY_ROLL_RADIANS_PER_UPDATE, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); } else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) { ApplyFlyingRoll( -FLY_ROLL_RADIANS_PER_UPDATE, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); } else { if (m_AngularVelocity.Z != 0) m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); } /* if (Flying && IsColliding && controlland) { // nesting this check because LengthSquared() is expensive and we don't // want to do it every step when flying. if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) StopFlying(); } */ } } else if (IsColliding && agent_control_v3.Z < 0f) agent_control_v3.Z = 0; // else if(AgentControlStopActive %% Velocity.Z <0.01f) // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); // If the agent update does move the avatar, then calculate the force ready for the velocity update, // which occurs later in the main scene loop // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the // avatar location in place). if (update_movementflag || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) { if (AgentControlStopActive) { // if (MovementFlag == 0 && Animator.Falling) if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling) { AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true); } else AddNewMovement(agent_control_v3, AgentControlStopSlowVel); } else { AddNewMovement(agent_control_v3); } } if (update_movementflag && ParentID == 0) { // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); Animator.UpdateMovementAnimations(); } SendControlsToScripts(flagsForScripts); } // We need to send this back to the client in order to see the edit beams if ((State & (uint)AgentState.Editing) != 0) SendAgentTerseUpdate(this); m_scene.EventManager.TriggerOnClientMovement(this); }
/// <summary> /// This is the event handler for client movement. If a client is moving, this event is triggering. /// </summary> public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { //if (m_isChildAgent) //{ // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); // return; //} m_perfMonMS = Util.EnvironmentTickCount(); ++m_movementUpdateCount; if (m_movementUpdateCount < 1) m_movementUpdateCount = 1; #region Sanity Checking // This is irritating. Really. if (!AbsolutePosition.IsFinite()) { RemoveFromPhysicalScene(); m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); m_pos = m_LastFinitePos; if (!m_pos.IsFinite()) { m_pos.X = 127f; m_pos.Y = 127f; m_pos.Z = 127f; m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); } AddToPhysicalScene(false); } else { m_LastFinitePos = m_pos; } #endregion Sanity Checking #region Inputs AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; Quaternion bodyRotation = agentData.BodyRotation; // Camera location in world. We'll need to raytrace // from this location from time to time. m_CameraCenter = agentData.CameraCenter; if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance) { ReprioritizeUpdates(); m_lastCameraCenter = m_CameraCenter; } // Use these three vectors to figure out what the agent is looking at // Convert it to a Matrix and/or Quaternion m_CameraAtAxis = agentData.CameraAtAxis; m_CameraLeftAxis = agentData.CameraLeftAxis; m_CameraUpAxis = agentData.CameraUpAxis; // The Agent's Draw distance setting m_DrawDistance = agentData.Far; // Check if Client has camera in 'follow cam' or 'build' mode. Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; #endregion Inputs if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) { StandUp(); } //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); // Raycast from the avatar's head to the camera to see if there's anything blocking the view if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) { if (m_followCamAuto) { Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); } } lock (scriptedcontrols) { if (scriptedcontrols.Count > 0) { SendControlToScripts((uint)flags); flags = RemoveIgnoredControls(flags, IgnoredControls); } } if (m_autopilotMoving) CheckAtSitTarget(); if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) { // TODO: This doesn't prevent the user from walking yet. // Setting parent ID would fix this, if we knew what value // to use. Or we could add a m_isSitting variable. //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); SitGround = true; } // In the future, these values might need to go global. // Here's where you get them. m_AgentControlFlags = flags; m_headrotation = agentData.HeadRotation; m_state = agentData.State; PhysicsActor actor = PhysicsActor; if (actor == null) { return; } bool update_movementflag = false; if (m_allowMovement) { if (agentData.UseClientAgentPosition) { m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; m_moveToPositionTarget = agentData.ClientAgentPosition; } int i = 0; bool update_rotation = false; bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; Quaternion q = bodyRotation; bool oldflying = PhysicsActor.Flying; if (m_forceFly) actor.Flying = true; else if (m_flyDisabled) actor.Flying = false; else actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); if (actor.Flying != oldflying) update_movementflag = true; if (q != m_bodyRot) { m_bodyRot = q; update_rotation = true; } if (m_parentID == 0) { bool bAllowUpdateMoveToPosition = false; bool bResetMoveToPosition = false; Vector3[] dirVectors; // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying // this prevents 'jumping' in inappropriate situations. if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying)) dirVectors = GetWalkDirectionVectors(); else dirVectors = Dir_Vectors; // The fact that m_movementflag is a byte needs to be fixed // it really should be a uint uint nudgehack = 250; foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint)flags & (uint)DCF) != 0) { bResetMoveToPosition = true; DCFlagKeyPressed = true; try { agent_control_v3 += dirVectors[i]; //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); } catch (IndexOutOfRangeException) { // Why did I get this? } if ((m_movementflag & (byte)(uint)DCF) == 0) { if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) { m_movementflag |= (byte)nudgehack; } m_movementflag += (byte)(uint)DCF; update_movementflag = true; } } else { if ((m_movementflag & (byte)(uint)DCF) != 0 || ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((m_movementflag & (byte)nudgehack) == nudgehack)) ) // This or is for Nudge forward { m_movementflag -= ((byte)(uint)DCF); update_movementflag = true; /* if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) && ((m_movementflag & (byte)nudgehack) == nudgehack)) { m_log.Debug("Removed Hack flag"); } */ } else { bAllowUpdateMoveToPosition = true; } } i++; } //Paupaw:Do Proper PID for Autopilot here if (bResetMoveToPosition) { m_moveToPositionTarget = Vector3.Zero; m_moveToPositionInProgress = false; update_movementflag = true; bAllowUpdateMoveToPosition = false; } if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) { //Check the error term of the current position in relation to the target position if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) { // we are close enough to the target m_moveToPositionTarget = Vector3.Zero; m_moveToPositionInProgress = false; update_movementflag = true; } else { try { // move avatar in 2D at one meter/second towards target, in avatar coordinate frame. // This movement vector gets added to the velocity through AddNewMovement(). // Theoretically we might need a more complex PID approach here if other // unknown forces are acting on the avatar and we need to adaptively respond // to such forces, but the following simple approach seems to works fine. Vector3 LocalVectorToTarget3D = (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords // Ignore z component of vector Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); LocalVectorToTarget2D.Normalize(); agent_control_v3 += LocalVectorToTarget2D; // update avatar movement flags. the avatar coordinate system is as follows: // // +X (forward) // // ^ // | // | // | // | // (left) +Y <--------o--------> -Y // avatar // | // | // | // | // v // -X // // based on the above avatar coordinate system, classify the movement into // one of left/right/back/forward. if (LocalVectorToTarget2D.Y > 0)//MoveLeft { m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; //AgentControlFlags AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; update_movementflag = true; } else if (LocalVectorToTarget2D.Y < 0) //MoveRight { m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; update_movementflag = true; } if (LocalVectorToTarget2D.X < 0) //MoveBack { m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; update_movementflag = true; } else if (LocalVectorToTarget2D.X > 0) //Move Forward { m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; update_movementflag = true; } } catch (Exception e) { //Avoid system crash, can be slower but... m_log.DebugFormat("Crash! {0}", e.ToString()); } } } } // Cause the avatar to stop flying if it's colliding // with something with the down arrow pressed. // Only do this if we're flying if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) { // Landing detection code // Are the landing controls requirements filled? bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); // Are the collision requirements fulfilled? bool colliding = (m_physicsActor.IsColliding == true); if (m_physicsActor.Flying && colliding && controlland) { // nesting this check because LengthSquared() is expensive and we don't // want to do it every step when flying. if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) StopFlying(); } } if (update_movementflag || (update_rotation && DCFlagKeyPressed)) { // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed)); // m_log.DebugFormat( // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); AddNewMovement(agent_control_v3, q); } } if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) Animator.UpdateMovementAnimations(); m_scene.EventManager.TriggerOnClientMovement(this); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); }
/// <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); }
public void CopyFrom(AgentData cAgent) { // DEBUG ON m_log.ErrorFormat("[SCENEPRESENCE] CALLING COPYFROM"); // DEBUG OFF m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; m_pos = cAgent.Position; m_velocity = cAgent.Velocity; m_CameraCenter = cAgent.Center; //m_avHeight = cAgent.Size.Z; m_CameraAtAxis = cAgent.AtAxis; m_CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; m_DrawDistance = cAgent.Far; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); m_headrotation = cAgent.HeadRotation; m_bodyRot = cAgent.BodyRotation; m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) m_godLevel = cAgent.GodLevel; m_setAlwaysRun = cAgent.AlwaysRun; m_appearance = new AvatarAppearance(cAgent.Appearance); /* uint i = 0; try { if (cAgent.Wearables == null) cAgent.Wearables = new UUID[0]; AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; for (uint n = 0; n < cAgent.Wearables.Length; n += 2) { UUID itemId = cAgent.Wearables[n]; UUID assetId = cAgent.Wearables[n + 1]; wears[i++] = new AvatarWearable(itemId, assetId); } // m_appearance.Wearables = wears; Primitive.TextureEntry textures = null; if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) textures = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); byte[] visuals = null; if ((cAgent.VisualParams != null) && (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) visuals = (byte[])cAgent.VisualParams.Clone(); m_appearance = new AvatarAppearance(cAgent.AgentID,wears,textures,visuals); } catch (Exception e) { m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); } // Attachments try { if (cAgent.Attachments != null) { m_appearance.ClearAttachments(); foreach (AvatarAttachment att in cAgent.Attachments) { m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); } } } catch { } */ try { lock (scriptedcontrols) { if (cAgent.Controllers != null) { scriptedcontrols.Clear(); foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; scriptedcontrols[sc.itemID] = sc; } } } } catch { } // Animations try { Animator.ResetAnimations(); Animator.Animations.FromArray(cAgent.Anims); } catch { } //cAgent.GroupID = ?? //Groups??? }