From 7f499ff3f386d57bcd81ebb3f58f110011100604 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 10 Aug 2011 23:56:19 +0100 Subject: [PATCH] Add a OS_NPC_LAND_AT_TARGET option to osMoveToTarget() Default for this function is now not to automatically land. This allows better control by scripts when an avatar is going to be landing on a prim rather than the ground. Stopping the avatar involves faking a collision, to avoid the pid controller making it overshoot. A better approach would be to gradually slow the avatar as we near the target --- .../Region/Framework/Interfaces/INPCModule.cs | 5 ++- .../OptionalModules/World/NPC/NPCAvatar.cs | 5 +++ .../OptionalModules/World/NPC/NPCModule.cs | 35 ++++++++++++------- .../World/NPC/Tests/NPCModuleTests.cs | 4 +-- .../Region/Physics/OdePlugin/ODECharacter.cs | 2 ++ .../Shared/Api/Implementation/OSSL_Api.cs | 11 ++++-- .../Shared/Api/Runtime/LSL_Constants.cs | 1 + 7 files changed, 45 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs index 06296c9d04..08b973dc3c 100644 --- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs +++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs @@ -71,8 +71,11 @@ namespace OpenSim.Region.Framework.Interfaces /// If true, then the avatar will attempt to walk to the location even if it's up in the air. /// This is to allow walking on prims. /// + /// + /// If true and the avatar is flying when it reaches the target, land. + /// /// True if the operation succeeded, false if there was no such agent or the agent was not an NPC - bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly); + bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget); /// /// Stop the NPC's current movement. diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index cfd692d307..d63c2a6705 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -37,6 +37,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC { public class NPCAvatar : IClientAPI { + /// + /// Signal whether the avatar should land when it reaches a move target + /// + public bool LandAtTarget { get; set; } + private readonly string m_firstname; private readonly string m_lastname; private readonly Vector3 m_startPos; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index d0b5a94ee1..f38af462c3 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -75,20 +75,26 @@ namespace OpenSim.Region.OptionalModules.World.NPC // We are close enough to the target m_log.DebugFormat("[NPC MODULE]: Stopping movement of npc {0}", presence.Name); - if (presence.PhysicsActor.Flying) - { - Vector3 targetPos = presence.MoveToPositionTarget; - float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; - if (targetPos.Z - terrainHeight < 0.2) - { - presence.PhysicsActor.Flying = false; - } - } - presence.Velocity = Vector3.Zero; presence.AbsolutePosition = presence.MoveToPositionTarget; presence.ResetMoveToTarget(); + if (presence.PhysicsActor.Flying) + { + for (int i = 0; i < 5; i++) + presence.PhysicsActor.IsColliding = true; + +// Vector3 targetPos = presence.MoveToPositionTarget; + if (m_avatars[presence.UUID].LandAtTarget) + presence.PhysicsActor.Flying = false; + +// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; +// if (targetPos.Z - terrainHeight < 0.2) +// { +// presence.PhysicsActor.Flying = false; +// } + } + // FIXME: This doesn't work if (presence.PhysicsActor.Flying) presence.Animator.TrySetMovementAnimation("HOVER"); @@ -217,7 +223,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC return npcAvatar.AgentId; } - public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly) + public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget) { lock (m_avatars) { @@ -227,8 +233,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC scene.TryGetScenePresence(agentID, out sp); m_log.DebugFormat( - "[NPC MODULE]: Moving {0} to {1} in {2}", sp.Name, pos, scene.RegionInfo.RegionName); + "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", + sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); + m_avatars[agentID].LandAtTarget = landAtTarget; sp.MoveToTarget(pos, noFly); return true; @@ -263,6 +271,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC { if (m_avatars.ContainsKey(agentID)) { + ScenePresence sp; + scene.TryGetScenePresence(agentID, out sp); + m_avatars[agentID].Say(text); return true; diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index 81497d53f2..d220fab409 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -113,7 +113,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); Vector3 targetPos = startPos + new Vector3(0, 0, 10); - npcModule.MoveToTarget(npc.UUID, scene, targetPos, false); + npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false); Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); @@ -135,7 +135,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests // Try a second movement startPos = npc.AbsolutePosition; targetPos = startPos + new Vector3(10, 0, 0); - npcModule.MoveToTarget(npc.UUID, scene, targetPos, false); + npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false); scene.Update(); diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 4f461ad47d..ecf5983539 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -305,10 +305,12 @@ namespace OpenSim.Region.Physics.OdePlugin { m_iscolliding = true; } + if (m_wascolliding != m_iscolliding) { //base.SendCollisionUpdate(new CollisionEventUpdate()); } + m_wascolliding = m_iscolliding; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 9b5d8d9252..f83304b156 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2209,11 +2209,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (module != null) { Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z); - module.MoveToTarget(new UUID(npc.m_string), World, pos, false); + module.MoveToTarget(new UUID(npc.m_string), World, pos, false, true); } } - public void osNpcMoveToTarget(LSL_Key npc, LSL_Vector position, int noFly) + public void osNpcMoveToTarget(LSL_Key npc, LSL_Vector position, int moveParams) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveToTarget"); @@ -2221,7 +2221,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (module != null) { Vector3 pos = new Vector3((float)position.x, (float)position.y, (float)position.z); - module.MoveToTarget(new UUID(npc.m_string), World, pos, noFly != 0); + module.MoveToTarget( + new UUID(npc.m_string), + World, + pos, + (moveParams & ScriptBaseClass.OS_NPC_NO_FLY) != 0, + (moveParams & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 9ed894c50a..e82c2815a2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -594,6 +594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase // Constants for osNpc* functions public const int OS_NPC_FLY = 0; public const int OS_NPC_NO_FLY = 1; + public const int OS_NPC_LAND_AT_TARGET = 2; public const string URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED"; public const string URL_REQUEST_DENIED = "URL_REQUEST_DENIED";