diff options
author | Melanie | 2011-12-17 12:31:25 +0100 |
---|---|---|
committer | Melanie | 2011-12-17 12:31:25 +0100 |
commit | 8a9a8ed5c903f3f685dfff2fd81a2c9594a12584 (patch) | |
tree | d7614cf4139be6b37eb901c9513d6f5f348f230f /OpenSim/Region/ScriptEngine/Shared/Api | |
parent | Merge branch 'master' into careminster (diff) | |
download | opensim-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')
3 files changed, 337 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 | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index c717589..231cd7e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | |||
@@ -165,6 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
165 | m_LSL_Functions.llBreakLink(linknum); | 165 | m_LSL_Functions.llBreakLink(linknum); |
166 | } | 166 | } |
167 | 167 | ||
168 | public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) | ||
169 | { | ||
170 | return m_LSL_Functions.llCastRay(start, end, options); | ||
171 | } | ||
172 | |||
168 | public LSL_Integer llCeil(double f) | 173 | public LSL_Integer llCeil(double f) |
169 | { | 174 | { |
170 | return m_LSL_Functions.llCeil(f); | 175 | return m_LSL_Functions.llCeil(f); |