/// <summary>
        ///     A partial implementation.
        ///     http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
        ///     So far only valid for standing/flying/ground sitting avatars and single prim objects.
        ///     If the object has multiple prims and/or a sitting avatar then the bounding
        ///     box is for the root prim only.
        /// </summary>
        public LSL_List llGetBoundingBox(string obj)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }

            UUID     objID  = UUID.Zero;
            LSL_List result = new LSL_List();

            if (!UUID.TryParse(obj, out objID))
            {
                result.Add(new LSL_Vector());
                result.Add(new LSL_Vector());
                return(result);
            }
            IScenePresence presence = World.GetScenePresence(objID);

            if (presence != null)
            {
                if (presence.ParentID == UUID.Zero) // not sat on an object
                {
                    LSL_Vector lower = new LSL_Vector();
                    LSL_Vector upper = new LSL_Vector();
                    if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
                        == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
                    {
                        // This is for ground sitting avatars
                        IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>();
                        if (appearance != null)
                        {
                            float height = appearance.Appearance.AvatarHeight / 2.66666667f;
                            lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
                            upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
                        }
                    }
                    else
                    {
                        // This is for standing/flying avatars
                        IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>();
                        if (appearance != null)
                        {
                            float height = appearance.Appearance.AvatarHeight / 2.0f;
                            lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
                            upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
                        }
                    }
                    result.Add(lower);
                    result.Add(upper);
                    return(result);
                }
                // sitting on an object so we need the bounding box of that
                // which should include the avatar so set the UUID to the
                // UUID of the object the avatar is sat on and allow it to fall through
                // to processing an object
                ISceneChildEntity p = World.GetSceneObjectPart(presence.ParentID);
                objID = p.UUID;
            }
            ISceneChildEntity part = World.GetSceneObjectPart(objID);

            // Currently only works for single prims without a sitting avatar
            if (part != null)
            {
                Vector3    halfSize = part.Scale * 0.5f;
                LSL_Vector lower    = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f);
                LSL_Vector upper    = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z);
                result.Add(lower);
                result.Add(upper);
                return(result);
            }

            // Not found so return empty values
            result.Add(new LSL_Vector());
            result.Add(new LSL_Vector());
            return(result);
        }
Exemplo n.º 2
0
 public LSL_List llDeleteSubList(LSL_List src, int start, int end)
 {
     return(src.DeleteSublist(start, end));
 }
        public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }

            LSL_List list = new LSL_List();

            Vector3 rayStart = start.ToVector3();
            Vector3 rayEnd   = end.ToVector3();
            Vector3 dir      = rayEnd - rayStart;

            float dist = Vector3.Mag(dir);

            int  count         = 1;
            bool detectPhantom = false;
            int  dataFlags     = 0;
            int  rejectTypes   = 0;

            for (int i = 0; i < options.Length; i += 2)
            {
                if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
                {
                    count = options.GetLSLIntegerItem(i + 1);
                }
                else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
                {
                    detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
                }
                else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
                {
                    dataFlags = options.GetLSLIntegerItem(i + 1);
                }
                else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
                {
                    rejectTypes = options.GetLSLIntegerItem(i + 1);
                }
            }

            if (count > 16)
            {
                count = 16;
            }
            else if (count <= 0)
            {
                Error("llCastRay", "You must request at least one result from llCastRay.");
                return(new LSL_List());
            }

            List <ContactResult> results = new List <ContactResult>();

            bool checkTerrain     = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
            bool checkAgents      = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
            bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
            bool checkPhysical    = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);


            if (checkAgents)
            {
                ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
                foreach (ContactResult r in agentHits)
                {
                    results.Add(r);
                }
            }

            if (checkPhysical || checkNonPhysical || detectPhantom)
            {
                ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom, count + 2);
                for (int iter = 0; iter < objectHits.Length; iter++)
                {
                    // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
                    objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
                    results.Add(objectHits[iter]);
                }
            }

            if (checkTerrain)
            {
                ContactResult?groundContact = GroundIntersection(rayStart, rayEnd);
                if (groundContact != null)
                {
                    results.Add((ContactResult)groundContact);
                }
            }

            results.Sort(delegate(ContactResult a, ContactResult b) {
                return(a.Depth.CompareTo(b.Depth));
            });

            int          values  = 0;
            ISceneEntity thisgrp = m_host.ParentEntity;

            foreach (ContactResult result in results)
            {
                if (result.Depth > dist)
                {
                    continue;
                }

                // physics ray can return colisions with host prim
                // this is supposed to happen
                if (m_host.LocalId == result.ConsumerID)
                {
                    continue;
                }

                if (!checkTerrain && result.ConsumerID == 0)
                {
                    continue; //Terrain
                }
                UUID itemID  = UUID.Zero;
                int  linkNum = 0;

                ISceneChildEntity part = World.GetSceneObjectPart(result.ConsumerID);
                // It's a prim!
                if (part != null)
                {
                    // dont detect members of same object ???
                    if (part.ParentEntity == thisgrp)
                    {
                        continue;
                    }

                    if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
                    {
                        itemID = part.ParentEntity.UUID;
                    }
                    else
                    {
                        itemID = part.UUID;
                    }

                    linkNum = part.LinkNum;
                }
                else
                {
                    IScenePresence sp = World.GetScenePresence(result.ConsumerID);
                    /// It it a boy? a girl?
                    if (sp != null)
                    {
                        itemID = sp.UUID;
                    }
                }

                list.Add(new LSL_String(itemID.ToString()));

                if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
                {
                    list.Add(new LSL_Integer(linkNum));
                }

                list.Add(new LSL_Vector(result.Pos));

                if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
                {
                    Vector3 norm = result.Normal * -1;
                    list.Add(new LSL_Vector(norm));
                }

                values++;
                if (values >= count)
                {
                    break;
                }
            }

            list.Add(new LSL_Integer(values));

            return(list);
        }