public void AddCollider(uint localID, ContactPoint contact)
 {
     Cleared = false;
     /*ContactPoint oldCol;
     if(!m_objCollisionList.TryGetValue(localID, out oldCol))
     {
         */
     lock (m_objCollisionList)
         m_objCollisionList[localID] = contact;
     /*}
     else
     {
         if(oldCol.PenetrationDepth < contact.PenetrationDepth)
             lock(m_objCollisionList)
                 m_objCollisionList[localID] = contact;
     }*/
 }
 public override void AddCollisionEvent(uint localID, ContactPoint contact)
 {
     CollisionCollection.AddCollider(localID, contact);
 }
Example #3
0
 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
 {
 }
Example #4
0
 public abstract void AddCollisionEvent(uint localID, ContactPoint contact);
        /// <summary>
        ///     Called from Simulate
        ///     This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name="timeStep"></param>
        /// <returns>True if the avatar should be removed from the simulation</returns>
        public void Move(float timeStep)
        {
            if (Body == IntPtr.Zero || !IsPhysical)
                return;

            Vector3 vec = Vector3.Zero;
            Vector3 vel = d.BodyGetLinearVel(Body).ToVector3();
            Vector3 tempPos = d.BodyGetPosition(Body).ToVector3();

            #region Flight Ceiling

            // rex, added height check

            if (_parent_scene.m_useFlightCeilingHeight && tempPos.Z > _parent_scene.m_flightCeilingHeight)
            {
                tempPos.Z = _parent_scene.m_flightCeilingHeight;
                d.BodySetPosition(Body, tempPos.X, tempPos.Y, tempPos.Z);
                if (vel.Z > 0.0f)
                {
                    vel.Z = 0.0f;
                    d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z);
                }
                if (m_targetVelocity.Z > 0.0f)
                    m_targetVelocity.Z = 0.0f;
            }

            // endrex

            #endregion

            #region NonFinite Pos

            Vector3 localPos = new Vector3(tempPos.X, tempPos.Y, tempPos.Z);

            if (!localPos.IsFinite())
            {
                MainConsole.Instance.Warn("[ODE Physics]: Avatar Position is non-finite!");

                _parent_scene.BadCharacter(this);
                return;
            }

            #endregion

            #region Check for out of region

            if (Position.X < 0.25f || Position.Y < 0.25f ||
                Position.X > _parent_scene.Region.RegionSizeX - .25f ||
                Position.Y > _parent_scene.Region.RegionSizeY - .25f)
            {
                if (!CheckForRegionCrossing())
                {
                    Vector3 newPos = Position;
                    newPos.X = Util.Clip(Position.X, 0.75f, _parent_scene.Region.RegionSizeX - 0.75f);
                    newPos.Y = Util.Clip(Position.Y, 0.75f, _parent_scene.Region.RegionSizeY - 0.75f);
                    Position = newPos;
                    d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
                }
            }

            #endregion

            #region Movement Multiplier

            float movementmult = 1f;
            if (!m_alwaysRun)
                movementmult /= _parent_scene.avMovementDivisorWalk;
            else
                movementmult /= _parent_scene.avMovementDivisorRun;

            movementmult *= 10;
            movementmult *= SpeedModifier;
            if (flying)
                movementmult *= _parent_scene.m_AvFlySpeed;

            #endregion

            #region Jump code

            if (IsJumping)
            {
                if (flying ||
                    ((IsColliding) && m_preJumpCounter > _parent_scene.m_preJumpTime || m_preJumpCounter > 150))
                {
                    m_isJumping = false;
                    m_preJumpCounter = 0;
                    m_targetVelocity.X /= 2;
                    m_targetVelocity.Y /= 2;
                    m_targetVelocity.Z = -0.5f;
                }
                else
                {
                    m_targetVelocity.X = m_preJumpForce.X * _parent_scene.m_preJumpForceMultiplierX / 2.5f;
                    m_targetVelocity.Y = m_preJumpForce.Y * _parent_scene.m_preJumpForceMultiplierY / 2.5f;
                    m_preJumpCounter++;
                }
            }
            else if (m_ispreJumping)
            {
                if (m_preJumpCounter == _parent_scene.m_preJumpTime)
                {
                    m_ispreJumping = false;
                    m_targetVelocity.X = m_preJumpForce.X;
                    m_targetVelocity.Y = m_preJumpForce.Y;
                    m_targetVelocity.Z = m_preJumpForce.Z *
                                         (m_alwaysRun
                                              ? _parent_scene.m_preJumpForceMultiplierZ/2.5f
                                              : _parent_scene.m_preJumpForceMultiplierZ/2.25f);

                    m_preJumpCounter = 0;
                    m_isJumping = true;
                }
                else
                {
                    m_preJumpCounter++;
                    TriggerMovementUpdate();
                    return;
                }
            }

            #endregion

            #region Check for underground

            d.AABB aabb;
            d.GeomGetAABB(Shell, out aabb);
            float chrminZ = aabb.MinZ;

            Vector3 posch = localPos;

            float ftmp;

            if (flying)
            {
                ftmp = 0.75f*timeStep;
                posch.X += vel.X*ftmp;
                posch.Y += vel.Y*ftmp;
            }

            float groundHeight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);

            if (chrminZ < groundHeight)
            {
                float depth = groundHeight - chrminZ;

                if (m_targetVelocity.Z < 0)
                    m_targetVelocity.Z = 0;

                if (!flying)
                {
                    if (vel.Z < -10f)
                        vel.Z = -10f;
                    vec.Z = -vel.Z*PID_D*1.5f + depth*PID_P*50.0f;
                }
                else
                {
                    vec.Z = depth*PID_P*50.0f;
                }

                if (depth < 0.12f)
                {
                    if (!m_iscolliding)
                    {
                        m_iscolliding = true;
                        m_colliderfilter = 15;

                        ContactPoint point = new ContactPoint
                                                 {
                                                     Type = ActorTypes.Ground,
                                                     PenetrationDepth = depth,
                                                     Position = {X = localPos.X, Y = localPos.Y, Z = chrminZ},
                                                     SurfaceNormal = new Vector3(0, 0, -1f)
                                                 };

                        //0 is the ground localID
                        AddCollisionEvent(0, point);
                    }
                    vec.Z *= 0.5f;
                }
            }
            /*
                        if(Flying && _target_velocity == Vector3.Zero &&
                            Math.Abs(vel.Z) < 0.1)
                            notMoving = true;
            */

            #endregion

            #region Gravity

            if (!flying)
                vec.Z += -9.8f * 35 * Mass
                    * ( _appliedFallingForce > 100 ? 1 : _appliedFallingForce++/100f)
                    * (IsTruelyColliding ? 0.5f : 1.0f);
            
            else if (_parent_scene.AllowAvGravity && m_targetVelocity.Z > 0 &&
                     tempPos.Z > _parent_scene.AvGravityHeight) //Should be stop avies from flying upwards
            {
                //How much should we force them down?
                float Multiplier = (_parent_scene.AllowAvsToEscapeGravity ? .03f : .1f);
                //How much should we force them down?
                float fudgeHeight = (_parent_scene.AllowAvsToEscapeGravity ? 80 : 30);
                //We add the 30 so that gravity is resonably strong once they pass the min height
                Multiplier *= tempPos.Z + fudgeHeight - _parent_scene.AvGravityHeight;

                //Limit these so that things don't go wrong
                if (Multiplier < 1)
                    Multiplier = 1;

                float maxpower = (_parent_scene.AllowAvsToEscapeGravity ? 1.5f : 3f);

                if (Multiplier > maxpower)
                    Multiplier = maxpower;

                m_targetVelocity.Z /= Multiplier;
                vel.Z /= Multiplier;
            }
            if (IsColliding)
                _appliedFallingForce = 10;

            #endregion

            #region Auto Fly Height
            if (Flying)
            {

                //Added for auto fly height. Kitto Flora
                //Changed to only check if the avatar is flying around,

                // Revolution: If the avatar is going down, they are trying to land (probably), so don't push them up to make it harder
                //   Only if they are moving around sideways do we need to push them up
                if (m_targetVelocity.X != 0 || m_targetVelocity.Y != 0)
                {
                    Vector3 forwardVel = new Vector3(m_targetVelocity.X > 0 ? 2 : (m_targetVelocity.X < 0 ? -2 : 0),
                                                     m_targetVelocity.Y > 0 ? 2 : (m_targetVelocity.Y < 0 ? -2 : 0),
                                                     0);
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y) +
                                            MinimumGroundFlightOffset;

                    //We cheat a bit and do a bit lower than normal
                    if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude ||
                        (tempPos.Z - CAPSULE_LENGTH) <
                        _parent_scene.GetTerrainHeightAtXY(tempPos.X + forwardVel.X, tempPos.Y + forwardVel.Y)
                        + MinimumGroundFlightOffset)
                        if (m_targetVelocity.Z < 0)
                            vec.Z += (target_altitude - tempPos.Z) * PID_D * 0.5f; //Don't apply so much
                        else if ((tempPos.Z - CAPSULE_LENGTH) + 5 < target_altitude)
                            vec.Z += (target_altitude - tempPos.Z) * PID_D * 3.05f;
                        else
                            vec.Z += (target_altitude - tempPos.Z) * PID_D * 1.75f;
                }
                else
                {
                    //Straight up and down, only apply when they are very close to the ground
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y);

                    if ((tempPos.Z - CAPSULE_LENGTH + (MinimumGroundFlightOffset / 1.5)) <
                        target_altitude + MinimumGroundFlightOffset)
                    {
                        if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude + 1)
                        {
                            vec.Z += ((target_altitude + 4) - (tempPos.Z - CAPSULE_LENGTH)) * PID_D;
                        }
                        else
                            vec.Z += ((target_altitude + MinimumGroundFlightOffset) - (tempPos.Z - CAPSULE_LENGTH)) *
                                     PID_D * 0.5f;
                    }
                }
            }

            #endregion

            #region Force application

            #region Force push application

            bool noDisable = false;
            if (_target_force != Vector3.Zero)
            {
                _target_vel_force = _target_force/2;
                _target_force = Vector3.Zero;
                noDisable = true;
            }
            if (_target_vel_force.X != 0)
                vec.X += (_target_vel_force.X)*PID_D*2;
            if (_target_vel_force.Y != 0)
                vec.Y += (_target_vel_force.Y)*PID_D*2;
            if (_target_vel_force.Z != 0)
                vec.Z += (_target_vel_force.Z)*PID_D;

            #endregion

            if (!flying && !IsTruelyColliding)
            {
                //Falling, and haven't yet hit the ground
                vec.X += ((m_targetVelocity.X + m_forceAppliedBeforeFalling.X) * movementmult - vel.X) * PID_D * 2;
                vec.Y += ((m_targetVelocity.Y + m_forceAppliedBeforeFalling.Y) * movementmult - vel.Y) * PID_D * 2;
                vec.Z += ((m_targetVelocity.Z + m_forceAppliedBeforeFalling.Z) * movementmult - vel.Z) * PID_D;
            }
            else
            {
                m_forceAppliedBeforeFalling = !flying ? Vector3.Zero : m_targetVelocity;

                vec.X += (m_targetVelocity.X * movementmult - vel.X) * PID_D * 2;
                vec.Y += (m_targetVelocity.Y * movementmult - vel.Y) * PID_D * 2;
                vec.Z += (m_targetVelocity.Z * movementmult - vel.Z) * PID_D;
            }

            Vector3 combinedForceVelocity = m_targetVelocity + _target_vel_force;
            if ((combinedForceVelocity == Vector3.Zero ||
                 (Math.Abs(combinedForceVelocity.X) < 0.01f &&
                  Math.Abs(combinedForceVelocity.Y) < 0.01f &&
                  Math.Abs(combinedForceVelocity.Z) < 0.01f)) &&
                Math.Abs(vel.X) < 0.1 && Math.Abs(vel.Y) < 0.1 &&
                Math.Abs(vel.Z) < 0.1 && !(_appliedFallingForce > 0) && !noDisable)
            {
                //Body isn't moving, disable it
                m_targetVelocity = Vector3.Zero;
                _target_vel_force = Vector3.Zero;
                d.BodySetLinearVel(Body, 0, 0, 0);
                d.BodyDisable(Body);
            }
            else
            {
                m_targetVelocity *= _parent_scene.AvDecayTime;
                _target_vel_force *= _parent_scene.AvDecayTime;
                d.BodyEnable(Body);
                d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
            }

            #endregion
        }
        /// <summary>
        ///     This is our near callback.  A geometry is near a body
        /// </summary>
        /// <param name="space">The space that contains the geoms.  Remember, spaces are also geoms</param>
        /// <param name="g1">a geometry or space</param>
        /// <param name="g2">another geometry or space</param>
        private void near(IntPtr space, IntPtr g1, IntPtr g2)
        {
            if (g1 == IntPtr.Zero || g2 == IntPtr.Zero || g1 == g2 || !ContinueCollisionProcessing)
                return;

            // Test if we're colliding a geom with a space.
            // If so we have to drill down into the space recursively
            if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
            {
                // Separating static prim geometry spaces.
                // We'll be calling near recursivly if one
                // of them is a space to find all of the
                // contact points in the space
                try
                {
                    d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
                }
                catch (Exception e)
                {
                    MainConsole.Instance.WarnFormat("[PHYSICS]: SpaceCollide2 failed: {0} ", e);
                    return;
                }
                return;
            }
            IntPtr b1 = d.GeomGetBody(g1);
            IntPtr b2 = d.GeomGetBody(g2);

            // Figure out how many contact points we have
            int count = 0;
            try
            {
                // Colliding Geom To Geom
                // This portion of the function 'was' blatantly ripped off from BoxStack.cs

                if (g1 == g2)
                    return; // Can't collide with yourself

                if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
                    return;

                count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray,
                                     d.ContactGeom.unmanagedSizeOf);
            }
            catch (Exception e)
            {
                MainConsole.Instance.WarnFormat("[PHYSICS]:  ode Collide failed: {0} ", e.ToString());

                PhysicsActor badObj;
                if (actor_name_map.TryGetValue(g1, out badObj))
                    if (badObj is WhiteCoreODEPrim)
                        RemovePrim((WhiteCoreODEPrim) badObj);
                    else if (badObj is WhiteCoreODECharacter)
                        RemoveAvatar((WhiteCoreODECharacter) badObj);
                if (actor_name_map.TryGetValue(g2, out badObj))
                    if (badObj is WhiteCoreODEPrim)
                        RemovePrim((WhiteCoreODEPrim) badObj);
                    else if (badObj is WhiteCoreODECharacter)
                        RemoveAvatar((WhiteCoreODECharacter) badObj);
                return;
            }

            if (count == 0)
                return;

            PhysicsActor p1;
            PhysicsActor p2;

            if (!actor_name_map.TryGetValue(g1, out p1))
                p1 = PANull;

            if (!actor_name_map.TryGetValue(g2, out p2))
                p2 = PANull;

            if (p1.CollisionScore >= float.MaxValue - count)
                p1.CollisionScore = 0;
            p1.CollisionScore += count;

            if (p2.CollisionScore >= float.MaxValue - count)
                p2.CollisionScore = 0;
            p2.CollisionScore += count;

            ContactPoint maxDepthContact = new ContactPoint();
            d.ContactGeom curContact = new d.ContactGeom();
            // 20131224 not used            d.ContactGeom maxContact = new d.ContactGeom();

            int NotSkipedCount = 0;

            //StatContactLoopTime = CollectTime(() =>

            #region Contact Loop

            for (int i = 0; i < count; i++)
            {
                if (!GetCurContactGeom(i, ref curContact))
                    break;

                if (curContact.depth > maxDepthContact.PenetrationDepth)
                {
                    maxDepthContact.PenetrationDepth = curContact.depth;
                    maxDepthContact.Position.X = curContact.pos.X;
                    maxDepthContact.Position.Y = curContact.pos.Y;
                    maxDepthContact.Position.Z = curContact.pos.Z;
                    maxDepthContact.Type = (ActorTypes)p1.PhysicsActorType;
                    maxDepthContact.SurfaceNormal.X = curContact.normal.X;
                    maxDepthContact.SurfaceNormal.Y = curContact.normal.Y;
                    maxDepthContact.SurfaceNormal.Z = curContact.normal.Z;
            // 20131224 not used                    maxContact = curContact;
                }
            }
            if (p1 is WhiteCoreODECharacter || p2 is WhiteCoreODECharacter)
                //This really should be maxContact, but there are crashes that users have reported when this is used...
                //AddODECollision(maxContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount);
                AddODECollision(curContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount);
            else
            {
                for (int i = 0; i < count; i++)
                {
                    if (!GetCurContactGeom(i, ref curContact))
                        break;
                    AddODECollision(curContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount);
                }
            }

            #endregion

            //StatCollisionAccountingTime = CollectTime(() =>
            {
                if (NotSkipedCount > 0)
                {
                    if (NotSkipedCount > geomContactPointsStartthrottle)
                    {
                        // If there are more then 3 contact points, it's likely
                        // that we've got a pile of objects, so ...
                        // We don't want to send out hundreds of terse updates over and over again
                        // so lets throttle them and send them again after it's somewhat sorted out.
                        p2.ThrottleUpdates = true;
                    }
                }
                collision_accounting_events(p1, p2, maxDepthContact);
            } //);
        }
 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
 {
     if (!p2.SubscribedEvents() && !p1.SubscribedEvents())
         return;
     if (p1.SubscribedEvents())
         p1.AddCollisionEvent(p2.LocalID, contact);
     if (p2.SubscribedEvents())
         p2.AddCollisionEvent(p1.LocalID, contact);
 }
        private void AddODECollision(d.ContactGeom curContact, PhysicsActor p1, PhysicsActor p2, IntPtr b1, IntPtr b2,
            ContactPoint maxDepthContact, ref int NotSkipedCount)
        {
            IntPtr joint = IntPtr.Zero;

            bool p2col = true;

            // We only need to test p2 for 'jump crouch purposes'
            if (p2 is WhiteCoreODECharacter && p1.PhysicsActorType == (int) ActorTypes.Prim)
            {
                // Testing if the collision is at the feet of the avatar
                if ((p2.Position.Z - maxDepthContact.Position.Z) < (p2.Size.Z*0.5f))
                    p2col = false;
            }

            p2.IsTruelyColliding = true;
            p2.IsColliding = p2col;

            // Logic for collision handling
            // Note, that if *all* contacts are skipped (VolumeDetect)
            // The prim still detects (and forwards) collision events but
            // appears to be phantom for the world

            // No collision on volume detect prims
            if ((p1 is WhiteCoreODEPrim && p1.VolumeDetect) ||
                (p2 is WhiteCoreODEPrim && p2.VolumeDetect))
                return;

            if (curContact.depth < 0f)
                return; //Has to be penetrating

            if (m_filterCollisions &&
                checkDupe(curContact, p2.PhysicsActorType))
                return;
            if (m_filterCollisions)
                _perloopContact.Add(curContact);

            NotSkipedCount++;

            // If we're colliding against terrain
            if (p1.PhysicsActorType == (int) ActorTypes.Ground)
            {
                if (p2.PhysicsActorType == (int) ActorTypes.Prim)
                {
                    ((WhiteCoreODEPrim) p2).GetContactParam(p2, ref newGlobalcontact);

                    joint = CreateContacJoint(curContact);
                }
                else
                {
                    newGlobalcontact = new d.Contact();
                    newGlobalcontact.surface.mode |= d.ContactFlags.SoftERP;
                    newGlobalcontact.surface.mu = 75;
                    newGlobalcontact.surface.bounce = 0.1f;
                    newGlobalcontact.surface.soft_erp = 0.05025f;
                    //GetContactParam(0.0f, AvatarContactBounce, ref newGlobalcontact);
                    joint = CreateContacJoint(curContact);
                }
                //Can't collide against anything else, agents do their own ground checks
            }
            else if ((p1.PhysicsActorType == (int) ActorTypes.Agent) &&
                     (p2.PhysicsActorType == (int) ActorTypes.Agent))
            {
                GetContactParam(0.0f, AvatarContactBounce, ref newGlobalcontact);

                joint = CreateContacJoint(curContact);
            }
            else if (p1.PhysicsActorType == (int) ActorTypes.Prim)
            {
                //Add restitution and friction changes
                ((WhiteCoreODEPrim) p1).GetContactParam(p2, ref newGlobalcontact);

                joint = CreateContacJoint(curContact);
            }

            if (ContinueCollisionProcessing && joint != IntPtr.Zero)
            {
                d.JointAttach(joint, b1, b2);
                m_global_contactcount++;
                joint = IntPtr.Zero;
            }
        }
Example #9
0
 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
 {
     CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
 }
 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
 {
     if (base.SubscribedToCollisions() && SubscribedEvents())
         //If we don't have anything that we are going to trigger, don't even add
     {
         if (CollisionEventsThisFrame == null)
             CollisionEventsThisFrame = new CollisionEventUpdate();
         CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
     }
 }
 public override void AddCollisionEvent(uint collidedWith, ContactPoint contact)
 {
 }
 public abstract void AddCollisionEvent(uint collidedWith, ContactPoint contact);
Example #13
0
 public abstract void AddCollisionEvent(uint collidedWith, ContactPoint contact);
        public void PhysicsCollision(EventArgs e)
        {
            // single threaded here
            if (e == null)
                return;

            CollisionEventUpdate a = (CollisionEventUpdate) e;
            Dictionary<uint, ContactPoint> collissionswith = a.GetCollisionEvents();
            List<uint> thisHitColliders = new List<uint>();
            List<uint> startedColliders = new List<uint>();
            ContactPoint startedCollider = new ContactPoint();

            // calculate things that started colliding this time
            // and build up list of colliders this time
            foreach (uint localID in collissionswith.Keys)
            {
                thisHitColliders.Add(localID);
                if (!m_lastColliders.Contains(localID))
                {
                    startedCollider = collissionswith[localID];
                    startedColliders.Add(localID);
                }
                //MainConsole.Instance.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
            }

            // calculate things that ended colliding
            List<uint> endedColliders = m_lastColliders.Where(localID => !thisHitColliders.Contains(localID)).ToList();

            //add the items that started colliding this time to the last colliders list.
            m_lastColliders.AddRange(startedColliders);
            // remove things that ended colliding from the last colliders list
            foreach (uint localID in endedColliders)
                m_lastColliders.Remove(localID);

            if (m_parentGroup == null)
                return;
            if (m_parentGroup.IsDeleted)
                return;

            const string SoundGlassCollision = "6a45ba0b-5775-4ea8-8513-26008a17f873";
            const string SoundMetalCollision = "9e5c1297-6eed-40c0-825a-d9bcd86e3193";
            const string SoundStoneCollision = "9538f37c-456e-4047-81be-6435045608d4";
            const string SoundFleshCollision = "dce5fdd4-afe4-4ea1-822f-dd52cac46b08";
            const string SoundPlasticCollision = "0e24a717-b97e-4b77-9c94-b59a5a88b2da";
            const string SoundRubberCollision = "153c8bf7-fb89-4d89-b263-47e58b1b4774";
            const string SoundWoodCollision = "063c97d3-033a-4e9b-98d8-05c8074922cb";

            // play the sound.
            if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f)
            {
                SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, 0, 0);
            }
            else if (startedColliders.Count > 0)
            {
                switch (startedCollider.Type)
                {
                    case ActorTypes.Agent:
                        break; // Agents will play the sound so we don't

                    case ActorTypes.Ground:
                        SendSound(SoundWoodCollision, 1, true, 0, 0);
                        break; //Always play the click or thump sound when hitting ground

                    case ActorTypes.Prim:
                        switch (Material)
                        {
                            case (int) OpenMetaverse.Material.Flesh:
                                SendSound(SoundFleshCollision, 1, true, 0, 0);
                                break;
                            case (int) OpenMetaverse.Material.Glass:
                                SendSound(SoundGlassCollision, 1, true, 0, 0);
                                break;
                            case (int) OpenMetaverse.Material.Metal:
                                SendSound(SoundMetalCollision, 1, true, 0, 0);
                                break;
                            case (int) OpenMetaverse.Material.Plastic:
                                SendSound(SoundPlasticCollision, 1, true, 0, 0);
                                break;
                            case (int) OpenMetaverse.Material.Rubber:
                                SendSound(SoundRubberCollision, 1, true, 0, 0);
                                break;
                            case (int) OpenMetaverse.Material.Stone:
                                SendSound(SoundStoneCollision, 1, true, 0, 0);
                                break;
                            case (int) OpenMetaverse.Material.Wood:
                                SendSound(SoundWoodCollision, 1, true, 0, 0);
                                break;
                        }
                        break; //Play based on material type in prim2prim collisions

                    default:
                        break; //Unclear of what this object is, no sounds
                }
            }
            if (CollisionSprite != UUID.Zero && CollisionSoundVolume > 0.0f)
                // The collision volume isn't a mistake, its an SL feature/bug
            {
                // TODO: make a sprite!
            }
            if (((AggregateScriptEvents & scriptEvents.collision) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
                (CollisionSound != UUID.Zero) ||
                PassCollisions != 2)
            {
                if ((AggregateScriptEvents & scriptEvents.collision_start) != 0 ||
                    (AggregateScriptEvents & scriptEvents.collision) != 0)
                {
                    // do event notification
                    if (startedColliders.Count > 0)
                    {
                        ColliderArgs StartCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in startedColliders)
                        {
                            if (localId != 0)
                            {
                                // always running this check because if the user deletes the object it would return a null reference.
                                if (m_parentGroup == null)
                                    return;

                                if (m_parentGroup.Scene == null)
                                    return;

                                ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
                                string data = "";
                                if (obj != null)
                                {
                                    if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
                                        m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object
                                        if (found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID,
                                                                            nameStr = obj.Name,
                                                                            ownerUUID = obj.OwnerID,
                                                                            posVector = obj.AbsolutePosition,
                                                                            rotQuat = obj.GetWorldRotation(),
                                                                            velVector = obj.Velocity,
                                                                            colliderType = 0,
                                                                            groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                            //If it is 0, it is to not accept collisions from this object
                                        else
                                        {
                                        }
                                    }
                                    else
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
                                        if (!found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID,
                                                                            nameStr = obj.Name,
                                                                            ownerUUID = obj.OwnerID,
                                                                            posVector = obj.AbsolutePosition,
                                                                            rotQuat = obj.GetWorldRotation(),
                                                                            velVector = obj.Velocity,
                                                                            colliderType = 0,
                                                                            groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                    }
                                }
                                else
                                {
                                    IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
                                    if (av != null)
                                    {
                                        if (av.LocalId == localId)
                                        {
                                            if (
                                                m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
                                                m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
                                                                                                                out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar
                                                if (found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID,
                                                                                    nameStr = av.ControllingClient.Name,
                                                                                    ownerUUID = av.UUID,
                                                                                    posVector = av.AbsolutePosition,
                                                                                    rotQuat = av.Rotation,
                                                                                    velVector = av.Velocity,
                                                                                    colliderType = 0,
                                                                                    groupUUID =
                                                                                        av.ControllingClient
                                                                                          .ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                                    //If it is 0, it is to not accept collisions from this avatar
                                                else
                                                {
                                                }
                                            }
                                            else
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
                                                                                                                out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
                                                if (!found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID,
                                                                                    nameStr = av.ControllingClient.Name,
                                                                                    ownerUUID = av.UUID,
                                                                                    posVector = av.AbsolutePosition,
                                                                                    rotQuat = av.Rotation,
                                                                                    velVector = av.Velocity,
                                                                                    colliderType = 0,
                                                                                    groupUUID =
                                                                                        av.ControllingClient
                                                                                          .ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (colliding.Count > 0)
                        {
                            StartCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;
                            //Always send to the prim it is occuring to
                            m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(this, StartCollidingMessage);
                            if ((UUID != ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (PassCollisions == PASS_NEVER)
                                {
                                }
                                if (PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(
                                        ParentGroup.RootPart, StartCollidingMessage);
                                }
                                else if (((ScriptEvents & scriptEvents.collision_start) == 0) &&
                                         PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(
                                        ParentGroup.RootPart, StartCollidingMessage);
                                }
                            }
                        }
                    }
                }

                if ((AggregateScriptEvents & scriptEvents.collision) != 0)
                {
                    if (m_lastColliders.Count > 0)
                    {
                        ColliderArgs CollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in m_lastColliders)
                        {
                            if (localId != 0)
                            {
                                if (m_parentGroup == null)
                                    return;

                                if (m_parentGroup.Scene == null)
                                    return;

                                ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
                                string data = "";
                                if (obj != null)
                                {
                                    if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
                                        m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object
                                        if (found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID,
                                                                            nameStr = obj.Name,
                                                                            ownerUUID = obj.OwnerID,
                                                                            posVector = obj.AbsolutePosition,
                                                                            rotQuat = obj.GetWorldRotation(),
                                                                            velVector = obj.Velocity,
                                                                            colliderType = 0,
                                                                            groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                            //If it is 0, it is to not accept collisions from this object
                                        else
                                        {
                                        }
                                    }
                                    else
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
                                        if (!found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID,
                                                                            nameStr = obj.Name,
                                                                            ownerUUID = obj.OwnerID,
                                                                            posVector = obj.AbsolutePosition,
                                                                            rotQuat = obj.GetWorldRotation(),
                                                                            velVector = obj.Velocity,
                                                                            colliderType = 0,
                                                                            groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                    }
                                }
                                else
                                {
                                    IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
                                    if (av != null)
                                    {
                                        if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
                                            m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
                                        {
                                            bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                            //If it is 1, it is to accept ONLY collisions from this avatar
                                            if (found)
                                            {
                                                DetectedObject detobj = new DetectedObject
                                                                            {
                                                                                keyUUID = av.UUID,
                                                                                nameStr = av.ControllingClient.Name,
                                                                                ownerUUID = av.UUID,
                                                                                posVector = av.AbsolutePosition,
                                                                                rotQuat = av.Rotation,
                                                                                velVector = av.Velocity,
                                                                                colliderType = 0,
                                                                                groupUUID =
                                                                                    av.ControllingClient.ActiveGroupId
                                                                            };
                                                colliding.Add(detobj);
                                            }
                                                //If it is 0, it is to not accept collisions from this avatar
                                        }
                                        else
                                        {
                                            bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                            //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
                                            if (!found)
                                            {
                                                DetectedObject detobj = new DetectedObject
                                                                            {
                                                                                keyUUID = av.UUID,
                                                                                nameStr = av.ControllingClient.Name,
                                                                                ownerUUID = av.UUID,
                                                                                posVector = av.AbsolutePosition,
                                                                                rotQuat = av.Rotation,
                                                                                velVector = av.Velocity,
                                                                                colliderType = 0,
                                                                                groupUUID =
                                                                                    av.ControllingClient.ActiveGroupId
                                                                            };
                                                colliding.Add(detobj);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (colliding.Count > 0)
                        {
                            CollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptColliding(this, CollidingMessage);

                            if ((UUID != ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (PassCollisions == PASS_NEVER)
                                {
                                }
                                if (PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptColliding(ParentGroup.RootPart,
                                                                                            CollidingMessage);
                                }
                                else if (((ScriptEvents & scriptEvents.collision) == 0) &&
                                         PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptColliding(
                                        ParentGroup.RootPart, CollidingMessage);
                                }
                            }
                        }
                    }
                }

                if ((AggregateScriptEvents & scriptEvents.collision_end) != 0)
                {
                    if (endedColliders.Count > 0)
                    {
                        ColliderArgs EndCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in endedColliders)
                        {
                            if (localId != 0)
                            {
                                // always running this check because if the user deletes the object it would return a null reference.
                                if (m_parentGroup == null)
                                    return;
                                if (m_parentGroup.Scene == null)
                                    return;
                                ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
                                string data = "";
                                if (obj != null)
                                {
                                    if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
                                        m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object
                                        if (found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID,
                                                                            nameStr = obj.Name,
                                                                            ownerUUID = obj.OwnerID,
                                                                            posVector = obj.AbsolutePosition,
                                                                            rotQuat = obj.GetWorldRotation(),
                                                                            velVector = obj.Velocity,
                                                                            colliderType = 0,
                                                                            groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                            //If it is 0, it is to not accept collisions from this object
                                        else
                                        {
                                        }
                                    }
                                    else
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
                                        if (!found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID,
                                                                            nameStr = obj.Name,
                                                                            ownerUUID = obj.OwnerID,
                                                                            posVector = obj.AbsolutePosition,
                                                                            rotQuat = obj.GetWorldRotation(),
                                                                            velVector = obj.Velocity,
                                                                            colliderType = 0,
                                                                            groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                    }
                                }
                                else
                                {
                                    IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
                                    if (av != null)
                                    {
                                        if (av.LocalId == localId)
                                        {
                                            if (
                                                m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
                                                m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
                                                                                                                out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar
                                                if (found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID,
                                                                                    nameStr = av.ControllingClient.Name,
                                                                                    ownerUUID = av.UUID,
                                                                                    posVector = av.AbsolutePosition,
                                                                                    rotQuat = av.Rotation,
                                                                                    velVector = av.Velocity,
                                                                                    colliderType = 0,
                                                                                    groupUUID =
                                                                                        av.ControllingClient
                                                                                          .ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                                    //If it is 0, it is to not accept collisions from this avatar
                                                else
                                                {
                                                }
                                            }
                                            else
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
                                                                                                                out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
                                                if (!found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID,
                                                                                    nameStr = av.ControllingClient.Name,
                                                                                    ownerUUID = av.UUID,
                                                                                    posVector = av.AbsolutePosition,
                                                                                    rotQuat = av.Rotation,
                                                                                    velVector = av.Velocity,
                                                                                    colliderType = 0,
                                                                                    groupUUID =
                                                                                        av.ControllingClient
                                                                                          .ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (colliding.Count > 0)
                        {
                            EndCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(this, EndCollidingMessage);

                            if ((UUID != ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (PassCollisions == PASS_NEVER)
                                {
                                }
                                if (PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(
                                        ParentGroup.RootPart, EndCollidingMessage);
                                }
                                else if (((ScriptEvents & scriptEvents.collision_end) == 0) &&
                                         PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(
                                        ParentGroup.RootPart, EndCollidingMessage);
                                }
                            }
                        }
                    }
                }
                if ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0 ||
                    (AggregateScriptEvents & scriptEvents.land_collision) != 0)
                {
                    if (startedColliders.Count > 0)
                    {
                        ColliderArgs LandStartCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = (from localId in startedColliders
                                                          where localId == 0
                                                          select new DetectedObject
                                                                     {
                                                                         keyUUID = UUID.Zero,
                                                                         nameStr = "",
                                                                         ownerUUID = UUID.Zero,
                                                                         posVector =
                                                                             m_parentGroup.RootPart.AbsolutePosition,
                                                                         rotQuat = Quaternion.Identity,
                                                                         velVector = Vector3.Zero,
                                                                         colliderType = 0,
                                                                         groupUUID = UUID.Zero
                                                                     }).ToList();

                        if (colliding.Count > 0)
                        {
                            LandStartCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(this, LandStartCollidingMessage);

                            if ((UUID != ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (PassCollisions == PASS_NEVER)
                                {
                                }
                                if (PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(
                                        ParentGroup.RootPart, LandStartCollidingMessage);
                                }
                                else if (((ScriptEvents & scriptEvents.land_collision_start) == 0) &&
                                         PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(
                                        ParentGroup.RootPart, LandStartCollidingMessage);
                                }
                            }
                        }
                    }
                }
                if ((AggregateScriptEvents & scriptEvents.land_collision) != 0)
                {
                    if (m_lastColliders.Count > 0)
                    {
                        ColliderArgs LandCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in m_lastColliders)
                        {
                            if (localId == 0)
                            {
                                //Hope that all is left is ground!
                                DetectedObject detobj = new DetectedObject
                                                            {
                                                                keyUUID = UUID.Zero,
                                                                nameStr = "",
                                                                ownerUUID = UUID.Zero,
                                                                posVector = m_parentGroup.RootPart.AbsolutePosition,
                                                                rotQuat = Quaternion.Identity,
                                                                velVector = Vector3.Zero,
                                                                colliderType = 0,
                                                                groupUUID = UUID.Zero
                                                            };
                                colliding.Add(detobj);
                            }
                        }

                        if (colliding.Count > 0)
                        {
                            LandCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(this, LandCollidingMessage);

                            if ((UUID != ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (PassCollisions == PASS_NEVER)
                                {
                                }
                                if (PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(
                                        ParentGroup.RootPart,
                                        LandCollidingMessage);
                                }
                                else if (((ScriptEvents & scriptEvents.land_collision) == 0) &&
                                         PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(
                                        ParentGroup.RootPart, LandCollidingMessage);
                                }
                            }
                        }
                    }
                }
                if ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0)
                {
                    if (endedColliders.Count > 0)
                    {
                        ColliderArgs LandEndCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = (from localId in startedColliders
                                                          where localId == 0
                                                          select new DetectedObject
                                                                     {
                                                                         keyUUID = UUID.Zero,
                                                                         nameStr = "",
                                                                         ownerUUID = UUID.Zero,
                                                                         posVector =
                                                                             m_parentGroup.RootPart.AbsolutePosition,
                                                                         rotQuat = Quaternion.Identity,
                                                                         velVector = Vector3.Zero,
                                                                         colliderType = 0,
                                                                         groupUUID = UUID.Zero
                                                                     }).ToList();

                        if (colliding.Count > 0)
                        {
                            LandEndCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(this, LandEndCollidingMessage);

                            if ((UUID != ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (PassCollisions == PASS_NEVER)
                                {
                                }
                                if (PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(
                                        ParentGroup.RootPart, LandEndCollidingMessage);
                                }
                                else if (((ScriptEvents & scriptEvents.land_collision_end) == 0) &&
                                         PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(
                                        ParentGroup.RootPart, LandEndCollidingMessage);
                                }
                            }
                        }
                    }
                }
            }
        }
 public abstract void AddCollisionEvent(uint localID, ContactPoint contact);