aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation
diff options
context:
space:
mode:
authorMelanie2011-12-17 12:31:25 +0100
committerMelanie2011-12-17 12:31:25 +0100
commit8a9a8ed5c903f3f685dfff2fd81a2c9594a12584 (patch)
treed7614cf4139be6b37eb901c9513d6f5f348f230f /OpenSim/Region/ScriptEngine/Shared/Api/Implementation
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC-8a9a8ed5c903f3f685dfff2fd81a2c9594a12584.zip
opensim-SC-8a9a8ed5c903f3f685dfff2fd81a2c9594a12584.tar.gz
opensim-SC-8a9a8ed5c903f3f685dfff2fd81a2c9594a12584.tar.bz2
opensim-SC-8a9a8ed5c903f3f685dfff2fd81a2c9594a12584.tar.xz
Fix hit testing link sets properly. Fix raycasting for LSL.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs425
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs5
2 files changed, 332 insertions, 98 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 5f5d3cb..42a2044 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
85 /// </summary> 85 /// </summary>
86 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 86 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
87 { 87 {
88// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 88 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
89 protected IScriptEngine m_ScriptEngine; 89 protected IScriptEngine m_ScriptEngine;
90 protected SceneObjectPart m_host; 90 protected SceneObjectPart m_host;
91 protected uint m_localID; 91 protected uint m_localID;
@@ -11124,153 +11124,382 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11124 { 11124 {
11125 m_SayShoutCount = 0; 11125 m_SayShoutCount = 0;
11126 } 11126 }
11127
11128 private struct Tri
11129 {
11130 public Vector3 p1;
11131 public Vector3 p2;
11132 public Vector3 p3;
11133 }
11134
11135 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11136 {
11137 float height = avatar.Appearance.AvatarHeight;
11138 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11139 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11140
11141 if (point.X > b1.X && point.X < b2.X &&
11142 point.Y > b1.Y && point.Y < b2.Y &&
11143 point.Z > b1.Z && point.Z < b2.Z)
11144 return true;
11145 return false;
11146 }
11147
11148 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11149 {
11150 List<ContactResult> contacts = new List<ContactResult>();
11151
11152 Vector3 ab = rayEnd - rayStart;
11153
11154 World.ForEachScenePresence(delegate(ScenePresence sp)
11155 {
11156 Vector3 ac = sp.AbsolutePosition - rayStart;
11157 Vector3 bc = sp.AbsolutePosition - rayEnd;
11158
11159 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11160
11161 if (d > 1.5)
11162 return;
11163
11164 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11165
11166 if (d2 > 0)
11167 return;
11168
11169 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11170 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11171
11172 if (!InBoundingBox(sp, p))
11173 return;
11174
11175 ContactResult result = new ContactResult ();
11176 result.ConsumerID = sp.LocalId;
11177 result.Depth = Vector3.Distance(rayStart, p);
11178 result.Normal = Vector3.Zero;
11179 result.Pos = p;
11180
11181 contacts.Add(result);
11182 });
11183
11184 return contacts.ToArray();
11185 }
11186
11187 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd)
11188 {
11189 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11190 List<ContactResult> contacts = new List<ContactResult>();
11191
11192 Vector3 ab = rayEnd - rayStart;
11193
11194 World.ForEachSOG(delegate(SceneObjectGroup group)
11195 {
11196 if (m_host.ParentGroup == group)
11197 return;
11198
11199 if (group.IsAttachment)
11200 return;
11201
11202 // Find the radius ouside of which we don't even need to hit test
11203 float minX;
11204 float maxX;
11205 float minY;
11206 float maxY;
11207 float minZ;
11208 float maxZ;
11209
11210 float radius = 0.0f;
11211
11212 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11213
11214 if (Math.Abs(minX) > radius)
11215 radius = Math.Abs(minX);
11216 if (Math.Abs(minY) > radius)
11217 radius = Math.Abs(minY);
11218 if (Math.Abs(minZ) > radius)
11219 radius = Math.Abs(minZ);
11220 if (Math.Abs(maxX) > radius)
11221 radius = Math.Abs(maxX);
11222 if (Math.Abs(maxY) > radius)
11223 radius = Math.Abs(maxY);
11224 if (Math.Abs(maxZ) > radius)
11225 radius = Math.Abs(maxZ);
11226
11227 Vector3 ac = group.AbsolutePosition - rayStart;
11228 Vector3 bc = group.AbsolutePosition - rayEnd;
11229
11230 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11231
11232 // Too far off ray, don't bother
11233 if (d > radius)
11234 return;
11235
11236 // Behind ray, drop
11237 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11238 if (d2 > 0)
11239 return;
11240
11241 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11242 // Miss.
11243 if (!intersection.HitTF)
11244 return;
11245
11246 ContactResult result = new ContactResult ();
11247 result.ConsumerID = group.LocalId;
11248 result.Depth = intersection.distance;
11249 result.Normal = intersection.normal;
11250 result.Pos = intersection.ipoint;
11251
11252 contacts.Add(result);
11253 });
11254
11255 return contacts.ToArray();
11256 }
11257
11258 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11259 {
11260 double[,] heightfield = World.Heightmap.GetDoubles();
11261 List<ContactResult> contacts = new List<ContactResult>();
11262
11263 double min = 2048.0;
11264 double max = 0.0;
11265
11266 // Find the min and max of the heightfield
11267 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11268 {
11269 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11270 {
11271 if (heightfield[x, y] > max)
11272 max = heightfield[x, y];
11273 if (heightfield[x, y] < min)
11274 min = heightfield[x, y];
11275 }
11276 }
11277
11278
11279 // A ray extends past rayEnd, but doesn't go back before
11280 // rayStart. If the start is above the highest point of the ground
11281 // and the ray goes up, we can't hit the ground. Ever.
11282 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11283 return null;
11284
11285 // Same for going down
11286 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11287 return null;
11288
11289 List<Tri> trilist = new List<Tri>();
11290
11291 // Create our triangle list
11292 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11293 {
11294 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11295 {
11296 Tri t1 = new Tri();
11297 Tri t2 = new Tri();
11298
11299 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11300 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11301 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11302 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11303
11304 t1.p1 = p1;
11305 t1.p2 = p2;
11306 t1.p3 = p3;
11307
11308 t2.p1 = p3;
11309 t2.p2 = p4;
11310 t2.p3 = p1;
11311
11312 trilist.Add(t1);
11313 trilist.Add(t2);
11314 }
11315 }
11316
11317 // Ray direction
11318 Vector3 rayDirection = rayEnd - rayStart;
11319
11320 foreach (Tri t in trilist)
11321 {
11322 // Compute triangle plane normal and edges
11323 Vector3 u = t.p2 - t.p1;
11324 Vector3 v = t.p3 - t.p1;
11325 Vector3 n = Vector3.Cross(u, v);
11326
11327 if (n == Vector3.Zero)
11328 continue;
11329
11330 Vector3 w0 = rayStart - t.p1;
11331 double a = -Vector3.Dot(n, w0);
11332 double b = Vector3.Dot(n, rayDirection);
11333
11334 // Not intersecting the plane, or in plane (same thing)
11335 // Ignoring this MAY cause the ground to not be detected
11336 // sometimes
11337 if (Math.Abs(b) < 0.000001)
11338 continue;
11339
11340 double r = a / b;
11341
11342 // ray points away from plane
11343 if (r < 0.0)
11344 continue;
11345
11346 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11347
11348 float uu = Vector3.Dot(u, u);
11349 float uv = Vector3.Dot(u, v);
11350 float vv = Vector3.Dot(v, v);
11351 Vector3 w = ip - t.p1;
11352 float wu = Vector3.Dot(w, u);
11353 float wv = Vector3.Dot(w, v);
11354 float d = uv * uv - uu * vv;
11355
11356 float cs = (uv * wv - vv * wu) / d;
11357 if (cs < 0 || cs > 1.0)
11358 continue;
11359 float ct = (uv * wu - uu * wv) / d;
11360 if (ct < 0 || (cs + ct) > 1.0)
11361 continue;
11362
11363 // Add contact point
11364 ContactResult result = new ContactResult ();
11365 result.ConsumerID = 0;
11366 result.Depth = Vector3.Distance(rayStart, ip);
11367 result.Normal = n;
11368 result.Pos = ip;
11369
11370 contacts.Add(result);
11371 }
11372
11373 if (contacts.Count == 0)
11374 return null;
11375
11376 contacts.Sort(delegate(ContactResult a, ContactResult b)
11377 {
11378 return (int)(a.Depth - b.Depth);
11379 });
11380
11381 return contacts[0];
11382 }
11383
11127 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11384 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
11128 { 11385 {
11386 LSL_List list = new LSL_List();
11387
11129 m_host.AddScriptLPS(1); 11388 m_host.AddScriptLPS(1);
11130 11389
11131 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11390 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
11132 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11391 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
11133 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11392 Vector3 dir = rayEnd - rayStart;
11134 11393
11135 int count = 0; 11394 int count = 1;
11136// int detectPhantom = 0; 11395 bool detectPhantom = false;
11137 int dataFlags = 0; 11396 int dataFlags = 0;
11138 int rejectTypes = 0; 11397 int rejectTypes = 0;
11139 11398
11140 for (int i = 0; i < options.Length; i += 2) 11399 for (int i = 0; i < options.Length; i += 2)
11141 { 11400 {
11142 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11401 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
11143 {
11144 count = options.GetLSLIntegerItem(i + 1); 11402 count = options.GetLSLIntegerItem(i + 1);
11145 } 11403 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
11146// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11404 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
11147// {
11148// detectPhantom = options.GetLSLIntegerItem(i + 1);
11149// }
11150 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11405 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
11151 {
11152 dataFlags = options.GetLSLIntegerItem(i + 1); 11406 dataFlags = options.GetLSLIntegerItem(i + 1);
11153 }
11154 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11407 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
11155 {
11156 rejectTypes = options.GetLSLIntegerItem(i + 1); 11408 rejectTypes = options.GetLSLIntegerItem(i + 1);
11157 }
11158 } 11409 }
11159 11410
11160 LSL_List list = new LSL_List(); 11411 if (count > 16)
11161 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11412 count = 16;
11162
11163 double distance = Util.GetDistanceTo(startvector, endvector);
11164 11413
11165 if (distance == 0) 11414 List<ContactResult> results = new List<ContactResult>();
11166 distance = 0.001;
11167
11168 Vector3 posToCheck = startvector;
11169 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
11170 11415
11171 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11416 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
11172 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11417 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
11173 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11418 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
11174 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11419 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
11175 11420
11176 for (float i = 0; i <= distance; i += 0.1f) 11421 if (checkTerrain)
11177 { 11422 {
11178 posToCheck = startvector + (dir * (i / (float)distance)); 11423 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11424 if (groundContact != null)
11425 results.Add((ContactResult)groundContact);
11426 }
11179 11427
11180 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11428 if (checkAgents)
11181 { 11429 {
11182 ContactResult result = new ContactResult(); 11430 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11183 result.ConsumerID = 0; 11431 foreach (ContactResult r in agentHits)
11184 result.Depth = 0; 11432 results.Add(r);
11185 result.Normal = Vector3.Zero; 11433 }
11186 result.Pos = posToCheck;
11187 results.Add(result);
11188 checkTerrain = false;
11189 }
11190 11434
11191 if (checkAgents) 11435 if (checkPhysical || checkNonPhysical)
11192 { 11436 {
11193 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11437 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd);
11194 { 11438 foreach (ContactResult r in objectHits)
11195 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) 11439 results.Add(r);
11196 {
11197 ContactResult result = new ContactResult ();
11198 result.ConsumerID = sp.LocalId;
11199 result.Depth = 0;
11200 result.Normal = Vector3.Zero;
11201 result.Pos = posToCheck;
11202 results.Add(result);
11203 }
11204 });
11205 }
11206 } 11440 }
11207 11441
11208 int refcount = 0; 11442 results.Sort(delegate(ContactResult a, ContactResult b)
11443 {
11444 return (int)(a.Depth - b.Depth);
11445 });
11446
11447 int values = 0;
11209 foreach (ContactResult result in results) 11448 foreach (ContactResult result in results)
11210 { 11449 {
11211 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11450 UUID itemID = UUID.Zero;
11212 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11451 int linkNum = 0;
11213 continue;
11214
11215 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
11216
11217 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS)
11218 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents
11219
11220 if (entity == null)
11221 {
11222 list.Add(UUID.Zero);
11223 11452
11224 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11453 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11225 list.Add(0); 11454 // It's a prim!
11226 11455 if (part != null)
11227 list.Add(result.Pos);
11228
11229 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
11230 list.Add(result.Normal);
11231
11232 continue; //Can't find it, so add UUID.Zero
11233 }
11234
11235 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
11236 ((ISceneChildEntity)intersection.obj).PhysActor == null)
11237 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
11238
11239 if (entity is SceneObjectPart)
11240 { 11456 {
11241 if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) 11457 if (part.PhysActor != null)
11242 { 11458 {
11243 if (!checkPhysical) 11459 if (part.PhysActor.IsPhysical && !checkPhysical)
11460 continue;
11461 if (!part.PhysActor.IsPhysical && !checkNonPhysical)
11244 continue; 11462 continue;
11245 } 11463 }
11246 else 11464 else
11247 { 11465 {
11248 if (!checkNonPhysical) 11466 if (!detectPhantom)
11249 continue; 11467 continue;
11250 } 11468 }
11251 }
11252 11469
11253 refcount++; 11470 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
11254 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11471 itemID = part.ParentGroup.UUID;
11255 list.Add(((SceneObjectPart)entity).ParentGroup.UUID); 11472 else
11256 else 11473 itemID = part.UUID;
11257 list.Add(entity.UUID);
11258 11474
11259 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11475 linkNum = part.LinkNum;
11476 }
11477 else
11260 { 11478 {
11261 if (entity is SceneObjectPart) 11479 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
11262 list.Add(((SceneObjectPart)entity).LinkNum); 11480 /// It it a boy? a girl?
11263 else 11481 if (sp != null)
11264 list.Add(0); 11482 itemID = sp.UUID;
11265 } 11483 }
11266 11484
11267 list.Add(result.Pos); 11485 list.Add(new LSL_String(itemID.ToString()));
11486 list.Add(new LSL_String(result.Pos.ToString()));
11487
11488 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11489 list.Add(new LSL_Integer(linkNum));
11490
11268 11491
11269 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11492 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
11270 list.Add(result.Normal); 11493 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11494
11495 values++;
11496 count--;
11497
11498 if (count == 0)
11499 break;
11271 } 11500 }
11272 11501
11273 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11502 list.Add(new LSL_Integer(values));
11274 11503
11275 return list; 11504 return list;
11276 } 11505 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 4da8fe7..91a7b87 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -431,6 +431,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
431 // avatar rotation. This may include a nonzero elevation if 431 // avatar rotation. This may include a nonzero elevation if
432 // in mouselook. 432 // in mouselook.
433 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 433 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
434 if (avatar == null)
435 return sensedEntities;
434 fromRegionPos = avatar.AbsolutePosition; 436 fromRegionPos = avatar.AbsolutePosition;
435 q = avatar.Rotation; 437 q = avatar.Rotation;
436 } 438 }
@@ -444,6 +446,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
444 446
445 Action<ScenePresence> senseEntity = new Action<ScenePresence>(delegate(ScenePresence presence) 447 Action<ScenePresence> senseEntity = new Action<ScenePresence>(delegate(ScenePresence presence)
446 { 448 {
449 if (presence.PresenceType == PresenceType.Npc)
450 return;
451
447 if (presence.IsDeleted || presence.IsChildAgent || presence.GodLevel > 0.0) 452 if (presence.IsDeleted || presence.IsChildAgent || presence.GodLevel > 0.0)
448 return; 453 return;
449 454