diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 83f8e1b0d5..afc43930fd 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -1,15278 +1,15278 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the OpenSimulator Project nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.Runtime.Remoting.Lifetime;
-using System.Text;
-using System.Threading;
-using System.Text.RegularExpressions;
-using Nini.Config;
-using log4net;
-using OpenMetaverse;
-using OpenMetaverse.Assets;
-using OpenMetaverse.Packets;
-using OpenMetaverse.Rendering;
-using OpenSim;
-using OpenSim.Framework;
-
-using OpenSim.Region.CoreModules;
-using OpenSim.Region.CoreModules.World.Land;
-using OpenSim.Region.CoreModules.World.Terrain;
-using OpenSim.Region.Framework.Interfaces;
-using OpenSim.Region.Framework.Scenes;
-using OpenSim.Region.Framework.Scenes.Animation;
-using OpenSim.Region.Framework.Scenes.Scripting;
-using OpenSim.Region.Physics.Manager;
-using OpenSim.Region.ScriptEngine.Shared;
-using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
-using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
-using OpenSim.Region.ScriptEngine.Interfaces;
-using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
-using OpenSim.Services.Interfaces;
-using GridRegion = OpenSim.Services.Interfaces.GridRegion;
-using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
-using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
-using AssetLandmark = OpenSim.Framework.AssetLandmark;
-using RegionFlags = OpenSim.Framework.RegionFlags;
-
-using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
-using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
-using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
-using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
-using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
-using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
-using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
-using System.Reflection;
-using System.Linq;
-using PermissionMask = OpenSim.Framework.PermissionMask;
-
-namespace OpenSim.Region.ScriptEngine.Shared.Api
-{
-    // MUST be a ref type
-    public class UserInfoCacheEntry
-    {
-        public int time;
-        public UserAccount account;
-        public PresenceInfo pinfo;
-    }
-
-    /// 
-    /// Contains all LSL ll-functions. This class will be in Default AppDomain.
-    /// 
-    public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
-    {
-        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
-        public int LlRequestAgentDataCacheTimeoutMs { get; set; }
-
-        protected IScriptEngine m_ScriptEngine;
-        protected SceneObjectPart m_host;
-
-        /// 
-        /// Used for script sleeps when we are using co-operative script termination.
-        /// 
-        /// null if co-operative script termination is not active
-        WaitHandle m_coopSleepHandle;
-
-        /// 
-        /// The timer used by the ScriptInstance to measure how long the script has executed.
-        /// 
-        private Stopwatch m_executionTimer;
-
-        /// 
-        /// The item that hosts this script
-        /// 
-        protected TaskInventoryItem m_item;
-
-        protected bool throwErrorOnNotImplemented = false;
-        protected AsyncCommandManager AsyncCommands = null;
-        protected float m_ScriptDelayFactor = 1.0f;
-        protected float m_ScriptDistanceFactor = 1.0f;
-        protected float m_MinTimerInterval = 0.5f;
-        protected float m_recoilScaleFactor = 0.0f;
-
-        protected DateTime m_timer = DateTime.Now;
-        protected bool m_waitingForScriptAnswer = false;
-        protected bool m_automaticLinkPermission = false;
-        protected IMessageTransferModule m_TransferModule = null;
-        protected int m_notecardLineReadCharsMax = 255;
-        protected int m_scriptConsoleChannel = 0;
-        protected bool m_scriptConsoleChannelEnabled = false;
-        protected IUrlModule m_UrlModule = null;
-        protected Dictionary m_userInfoCache = new Dictionary();
-        protected int EMAIL_PAUSE_TIME = 20;  // documented delay value for smtp.
-        protected int m_sleepMsOnSetTexture = 200;
-        protected int m_sleepMsOnSetLinkTexture = 200;
-        protected int m_sleepMsOnScaleTexture = 200;
-        protected int m_sleepMsOnOffsetTexture = 200;
-        protected int m_sleepMsOnRotateTexture = 200;
-        protected int m_sleepMsOnSetPos = 200;
-        protected int m_sleepMsOnSetRot = 200;
-        protected int m_sleepMsOnSetLocalRot = 200;
-        protected int m_sleepMsOnPreloadSound = 1000;
-        protected int m_sleepMsOnMakeExplosion = 100;
-        protected int m_sleepMsOnMakeFountain = 100;
-        protected int m_sleepMsOnMakeSmoke = 100;
-        protected int m_sleepMsOnMakeFire = 100;
-        protected int m_sleepMsOnRezAtRoot = 100;
-        protected int m_sleepMsOnInstantMessage = 2000;
-        protected int m_sleepMsOnEmail = 20000;
-        protected int m_sleepMsOnCreateLink = 1000;
-        protected int m_sleepMsOnGiveInventory = 3000;
-        protected int m_sleepMsOnRequestAgentData = 100;
-        protected int m_sleepMsOnRequestInventoryData = 1000;
-        protected int m_sleepMsOnSetDamage = 5000;
-        protected int m_sleepMsOnTextBox = 1000;
-        protected int m_sleepMsOnAdjustSoundVolume = 100;
-        protected int m_sleepMsOnEjectFromLand = 5000;
-        protected int m_sleepMsOnAddToLandPassList = 100;
-        protected int m_sleepMsOnDialog = 1000;
-        protected int m_sleepMsOnRemoteLoadScript = 3000;
-        protected int m_sleepMsOnRemoteLoadScriptPin = 3000;
-        protected int m_sleepMsOnOpenRemoteDataChannel = 1000;
-        protected int m_sleepMsOnSendRemoteData = 3000;
-        protected int m_sleepMsOnRemoteDataReply = 3000;
-        protected int m_sleepMsOnCloseRemoteDataChannel = 1000;
-        protected int m_sleepMsOnSetPrimitiveParams = 200;
-        protected int m_sleepMsOnSetLinkPrimitiveParams = 200;
-        protected int m_sleepMsOnXorBase64Strings = 300;
-        protected int m_sleepMsOnSetParcelMusicURL = 2000;
-        protected int m_sleepMsOnGetPrimMediaParams = 1000;
-        protected int m_sleepMsOnGetLinkMedia = 1000;
-        protected int m_sleepMsOnSetPrimMediaParams = 1000;
-        protected int m_sleepMsOnSetLinkMedia = 1000;
-        protected int m_sleepMsOnClearPrimMedia = 1000;
-        protected int m_sleepMsOnClearLinkMedia = 1000;
-        protected int m_sleepMsOnRequestSimulatorData = 1000;
-        protected int m_sleepMsOnLoadURL = 10000;
-        protected int m_sleepMsOnParcelMediaCommandList = 2000;
-        protected int m_sleepMsOnParcelMediaQuery = 2000;
-        protected int m_sleepMsOnModPow = 1000;
-        protected int m_sleepMsOnSetPrimURL = 2000;
-        protected int m_sleepMsOnRefreshPrimURL = 20000;
-        protected int m_sleepMsOnMapDestination = 1000;
-        protected int m_sleepMsOnAddToLandBanList = 100;
-        protected int m_sleepMsOnRemoveFromLandPassList = 100;
-        protected int m_sleepMsOnRemoveFromLandBanList = 100;
-        protected int m_sleepMsOnResetLandBanList = 100;
-        protected int m_sleepMsOnResetLandPassList = 100;
-        protected int m_sleepMsOnGetParcelPrimOwners = 2000;
-        protected int m_sleepMsOnGetNumberOfNotecardLines = 100;
-        protected int m_sleepMsOnGetNotecardLine = 100;
-        protected string m_internalObjectHost = "lsl.opensim.local";
-        protected bool m_restrictEmail = false;
-        protected ISoundModule m_SoundModule = null;
-
-        protected float m_avatarHeightCorrection = 0.2f;
-        protected bool m_useSimpleBoxesInGetBoundingBox = false;
-        protected bool m_addStatsInGetBoundingBox = false;
-
-        //LSL Avatar Bounding Box (lABB), lower (1) and upper (2),
-        //standing (Std), Groundsitting (Grs), Sitting (Sit),
-        //along X, Y and Z axes, constants (0) and coefficients (1)
-        protected float m_lABB1StdX0 = -0.275f;
-        protected float m_lABB2StdX0 = 0.275f;
-        protected float m_lABB1StdY0 = -0.35f;
-        protected float m_lABB2StdY0 = 0.35f;
-        protected float m_lABB1StdZ0 = -0.1f;
-        protected float m_lABB1StdZ1 = -0.5f;
-        protected float m_lABB2StdZ0 = 0.1f;
-        protected float m_lABB2StdZ1 = 0.5f;
-        protected float m_lABB1GrsX0 = -0.3875f;
-        protected float m_lABB2GrsX0 = 0.3875f;
-        protected float m_lABB1GrsY0 = -0.5f;
-        protected float m_lABB2GrsY0 = 0.5f;
-        protected float m_lABB1GrsZ0 = -0.05f;
-        protected float m_lABB1GrsZ1 = -0.375f;
-        protected float m_lABB2GrsZ0 = 0.5f;
-        protected float m_lABB2GrsZ1 = 0.0f;
-        protected float m_lABB1SitX0 = -0.5875f;
-        protected float m_lABB2SitX0 = 0.1875f;
-        protected float m_lABB1SitY0 = -0.35f;
-        protected float m_lABB2SitY0 = 0.35f;
-        protected float m_lABB1SitZ0 = -0.35f;
-        protected float m_lABB1SitZ1 = -0.375f;
-        protected float m_lABB2SitZ0 = -0.25f;
-        protected float m_lABB2SitZ1 = 0.25f;
-
-        protected float m_primSafetyCoeffX = 2.414214f;
-        protected float m_primSafetyCoeffY = 2.414214f;
-        protected float m_primSafetyCoeffZ = 1.618034f;
-        protected bool m_useCastRayV3 = false;
-        protected float m_floatToleranceInCastRay = 0.00001f;
-        protected float m_floatTolerance2InCastRay = 0.001f;
-        protected DetailLevel m_primLodInCastRay = DetailLevel.Medium;
-        protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium;
-        protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest;
-        protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium;
-        protected int m_maxHitsInCastRay = 16;
-        protected int m_maxHitsPerPrimInCastRay = 16;
-        protected int m_maxHitsPerObjectInCastRay = 16;
-        protected bool m_detectExitsInCastRay = false;
-        protected bool m_filterPartsInCastRay = false;
-        protected bool m_doAttachmentsInCastRay = false;
-        protected int m_msThrottleInCastRay = 200;
-        protected int m_msPerRegionInCastRay = 40;
-        protected int m_msPerAvatarInCastRay = 10;
-        protected int m_msMinInCastRay = 2;
-        protected int m_msMaxInCastRay = 40;
-        protected static List m_castRayCalls = new List();
-        protected bool m_useMeshCacheInCastRay = true;
-        protected static Dictionary m_cachedMeshes = new Dictionary();
-
-        //An array of HTTP/1.1 headers that are not allowed to be used
-        //as custom headers by llHTTPRequest.
-        private string[] HttpStandardHeaders =
-        {
-            "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language",
-            "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control",
-            "Connection", "Content-Encoding", "Content-Language",
-            "Content-Length", "Content-Location", "Content-MD5",
-            "Content-Range", "Content-Type", "Date", "ETag", "Expect",
-            "Expires", "From", "Host", "If-Match", "If-Modified-Since",
-            "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified",
-            "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
-            "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
-            "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent",
-            "Vary", "Via", "Warning", "WWW-Authenticate"
-        };
-
-        public void Initialize(
-            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle,
-            Stopwatch executionTimer)
-        {
-            m_ScriptEngine = scriptEngine;
-            m_host = host;
-            m_item = item;
-            m_coopSleepHandle = coopSleepHandle;
-            m_executionTimer = executionTimer;
-
-            LoadConfig();
-
-            m_TransferModule =
-                    m_ScriptEngine.World.RequestModuleInterface();
-            m_UrlModule = m_ScriptEngine.World.RequestModuleInterface();
-            m_SoundModule = m_ScriptEngine.World.RequestModuleInterface();
-
-            AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
-        }
-
-        /// 
-        /// Load configuration items that affect script, object and run-time behavior. */
-        /// 
-        private void LoadConfig()
-        {
-            LlRequestAgentDataCacheTimeoutMs = 20000;
-
-            IConfig seConfig = m_ScriptEngine.Config;
-
-            if (seConfig != null)
-            {
-                m_ScriptDelayFactor =
-                    seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor);
-                m_ScriptDistanceFactor =
-                    seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor);
-                m_MinTimerInterval =
-                    seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval);
-                m_automaticLinkPermission =
-                    seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission);
-                m_notecardLineReadCharsMax =
-                    seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax);
-
-                // Rezzing an object with a velocity can create recoil. This feature seems to have been
-                //    removed from recent versions of SL. The code computes recoil (vel*mass) and scales
-                //    it by this factor. May be zero to turn off recoil all together.
-                m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
-            }
-
-            if (m_notecardLineReadCharsMax > 65535)
-                m_notecardLineReadCharsMax = 65535;
-
-            // load limits for particular subsystems.
-            IConfigSource seConfigSource = m_ScriptEngine.ConfigSource;
-
-            if (seConfigSource != null)
-            {
-                IConfig lslConfig = seConfigSource.Configs["LL-Functions"];
-                if (lslConfig != null)
-                {
-                    m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail);
-                    m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection);
-                    m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox);
-                    m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox);
-                    m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0);
-                    m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0);
-                    m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0);
-                    m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0);
-                    m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0);
-                    m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1);
-                    m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0);
-                    m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1);
-                    m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0);
-                    m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0);
-                    m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0);
-                    m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0);
-                    m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0);
-                    m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1);
-                    m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0);
-                    m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1);
-                    m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0);
-                    m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0);
-                    m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0);
-                    m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0);
-                    m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0);
-                    m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1);
-                    m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0);
-                    m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1);
-                    m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX);
-                    m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY);
-                    m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ);
-                    m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3);
-                    m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay);
-                    m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay);
-                    m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay);
-                    m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay);
-                    m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay);
-                    m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay);
-                    m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay);
-                    m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
-                    m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
-                    m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
-                    m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
-                    m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
-                    m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay);
-                    m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay);
-                    m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay);
-                    m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay);
-                    m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay);
-                    m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay);
-                }
-
-                IConfig smtpConfig = seConfigSource.Configs["SMTP"];
-                if (smtpConfig != null) 
-                {
-                    // there's an smtp config, so load in the snooze time.
-                    EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
-
-                    m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
-                }
-            }
-            m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000;
-        }
-
-        public override Object InitializeLifetimeService()
-        {
-            ILease lease = (ILease)base.InitializeLifetimeService();
-
-            if (lease.CurrentState == LeaseState.Initial)
-            {
-                lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
-//                lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
-//                lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
-            }
-            return lease;
-        }
-
-        protected virtual void ScriptSleep(int delay)
-        {
-            delay = (int)((float)delay * m_ScriptDelayFactor);
-            if (delay == 0)
-                return;
-
-            Sleep(delay);
-        }
-
-        protected virtual void Sleep(int delay)
-        {
-            if (m_executionTimer != null)
-                m_executionTimer.Stop();    // sleep time doesn't count as execution time, since it doesn't use the CPU
-            
-            try
-            {
-                if (m_coopSleepHandle == null)
-                    System.Threading.Thread.Sleep(delay);
-                else
-                    CheckForCoopTermination(delay);
-            }
-            finally
-            {
-                if (m_executionTimer != null)
-                    m_executionTimer.Start();
-            }
-        }
-
-        /// 
-        /// Check for co-operative termination.
-        /// 
-        /// If called with 0, then just the check is performed with no wait.
-        protected virtual void CheckForCoopTermination(int delay)
-        {
-            if (m_coopSleepHandle.WaitOne(delay))
-                throw new ScriptCoopStopException();
-        }
-
-        public Scene World
-        {
-            get { return m_ScriptEngine.World; }
-        }
-
-        public void state(string newState)
-        {
-            m_ScriptEngine.SetState(m_item.ItemID, newState);
-        }
-
-        /// 
-        /// Reset the named script. The script must be present
-        /// in the same prim.
-        /// 
-        public void llResetScript()
-        {
-            m_host.AddScriptLPS(1);
-
-            // We need to tell the URL module, if we hav one, to release
-            // the allocated URLs
-            if (m_UrlModule != null)
-                m_UrlModule.ScriptRemoved(m_item.ItemID);
-
-            m_ScriptEngine.ApiResetScript(m_item.ItemID);
-        }
-
-        public void llResetOtherScript(string name)
-        {
-            UUID item;
-
-            m_host.AddScriptLPS(1);
-
-            if ((item = GetScriptByName(name)) != UUID.Zero)
-                m_ScriptEngine.ResetScript(item);
-            else
-                Error("llResetOtherScript", "Can't find script '" + name + "'");
-        }
-
-        public LSL_Integer llGetScriptState(string name)
-        {
-            UUID item;
-
-            m_host.AddScriptLPS(1);
-
-            if ((item = GetScriptByName(name)) != UUID.Zero)
-            {
-                return m_ScriptEngine.GetScriptState(item) ?1:0;
-            }
-
-            Error("llGetScriptState", "Can't find script '" + name + "'");
-
-            // If we didn't find it, then it's safe to
-            // assume it is not running.
-
-            return 0;
-        }
-
-        public void llSetScriptState(string name, int run)
-        {
-            UUID item;
-
-            m_host.AddScriptLPS(1);
-
-            // These functions are supposed to be robust,
-            // so get the state one step at a time.
-
-            if ((item = GetScriptByName(name)) != UUID.Zero)
-            {
-                m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
-            }
-            else
-            {
-                Error("llSetScriptState", "Can't find script '" + name + "'");
-            }
-        }
-
-        /// 
-        /// Get a given link entity from a linkset (linked objects and any sitting avatars).
-        /// 
-        /// 
-        /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then
-        /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset.
-        /// The ScenePresences receive linknums in the order in which they sat.
-        /// 
-        /// 
-        /// The link entity.  null if not found.
-        /// 
-        /// 
-        /// 
-        /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4).
-        /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned.
-        /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned.  If any
-        /// positive integer is given in this case then null is returned.
-        /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number
-        /// of entities, then the entity which corresponds to that linknum is returned.
-        /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then
-        /// null is returned.
-        /// 
-        public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum)
-        {
-            if (linknum < 0)
-            {
-                if (linknum == ScriptBaseClass.LINK_THIS)
-                    return part;
-                else
-                    return null;
-            }
-
-            int actualPrimCount = part.ParentGroup.PrimCount;
-            List sittingAvatars = part.ParentGroup.GetSittingAvatars();
-            int adjustedPrimCount = actualPrimCount + sittingAvatars.Count;
-
-            // Special case for a single prim.  In this case the linknum is zero.  However, this will not match a single
-            // prim that has any avatars sat upon it (in which case the root prim is link 1).
-            if (linknum == 0)
-            {
-                if (actualPrimCount == 1 && sittingAvatars.Count == 0)
-                    return part;
-
-                return null;
-            }
-            // Special case to handle a single prim with sitting avatars.  GetLinkPart() would only match zero but
-            // here we must match 1 (ScriptBaseClass.LINK_ROOT).
-            else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1)
-            {
-                if (sittingAvatars.Count > 0)
-                    return part.ParentGroup.RootPart;
-                else
-                    return null;
-            }
-            else if (linknum <= adjustedPrimCount)
-            {
-                if (linknum <= actualPrimCount)
-                {
-                    return part.ParentGroup.GetLinkNumPart(linknum);
-                }
-                else
-                {
-                    return sittingAvatars[linknum - actualPrimCount - 1];
-                }
-            }
-            else
-            {
-                return null;
-            }
-        }
-
-        public List GetLinkParts(int linkType)
-        {
-            return GetLinkParts(m_host, linkType);
-        }
-
-        public static List GetLinkParts(SceneObjectPart part, int linkType)
-        {
-            List ret = new List();
-            ret.Add(part);
-
-            switch (linkType)
-            {
-            case ScriptBaseClass.LINK_SET:
-                return new List(part.ParentGroup.Parts);
-
-            case ScriptBaseClass.LINK_ROOT:
-                ret = new List();
-                ret.Add(part.ParentGroup.RootPart);
-                return ret;
-
-            case ScriptBaseClass.LINK_ALL_OTHERS:
-                ret = new List(part.ParentGroup.Parts);
-
-                if (ret.Contains(part))
-                    ret.Remove(part);
-
-                return ret;
-
-            case ScriptBaseClass.LINK_ALL_CHILDREN:
-                ret = new List(part.ParentGroup.Parts);
-
-                if (ret.Contains(part.ParentGroup.RootPart))
-                    ret.Remove(part.ParentGroup.RootPart);
-                return ret;
-
-            case ScriptBaseClass.LINK_THIS:
-                return ret;
-
-            default:
-                if (linkType < 0)
-                    return new List();
-
-                SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
-                if (target == null)
-                    return new List();
-                ret = new List();
-                ret.Add(target);
-                return ret;
-            }
-        }
-
-        public List GetLinkEntities(int linkType)
-        {
-            return GetLinkEntities(m_host, linkType);
-        }
-
-        public List GetLinkEntities(SceneObjectPart part, int linkType)
-        {
-            List ret;
-
-            switch (linkType)
-            {
-                case ScriptBaseClass.LINK_SET:
-                    return new List(part.ParentGroup.Parts);
-
-                case ScriptBaseClass.LINK_ROOT:
-                    return new List() { part.ParentGroup.RootPart };
-
-                case ScriptBaseClass.LINK_ALL_OTHERS:
-                    ret = new List(part.ParentGroup.Parts);
-
-                    if (ret.Contains(part))
-                        ret.Remove(part);
-
-                    return ret;
-
-                case ScriptBaseClass.LINK_ALL_CHILDREN:
-                    ret = new List(part.ParentGroup.Parts);
-
-                    if (ret.Contains(part.ParentGroup.RootPart))
-                        ret.Remove(part.ParentGroup.RootPart);
-
-                    return ret;
-
-                case ScriptBaseClass.LINK_THIS:
-                    return new List() { part };
-
-                default:
-                    if (linkType < 0)
-                        return new List();
-
-                    ISceneEntity target = GetLinkEntity(part, linkType);
-                    if (target == null)
-                        return new List();
-
-                    return new List() { target };
-            }
-        }
-
-        //These are the implementations of the various ll-functions used by the LSL scripts.
-        public LSL_Float llSin(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Sin(f);
-        }
-
-        public LSL_Float llCos(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Cos(f);
-        }
-
-        public LSL_Float llTan(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Tan(f);
-        }
-
-        public LSL_Float llAtan2(double x, double y)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Atan2(x, y);
-        }
-
-        public LSL_Float llSqrt(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Sqrt(f);
-        }
-
-        public LSL_Float llPow(double fbase, double fexponent)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Pow(fbase, fexponent);
-        }
-
-        public LSL_Integer llAbs(int i)
-        {
-            // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
-            m_host.AddScriptLPS(1);
-            if (i == Int32.MinValue)
-                return i;
-            else
-                return (int)Math.Abs(i);
-        }
-
-        public LSL_Float llFabs(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Abs(f);
-        }
-
-        public LSL_Float llFrand(double mag)
-        {
-            m_host.AddScriptLPS(1);
-
-            return Util.RandomClass.NextDouble() * mag;
-        }
-
-        public LSL_Integer llFloor(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (int)Math.Floor(f);
-        }
-
-        public LSL_Integer llCeil(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (int)Math.Ceiling(f);
-        }
-
-        // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
-        public LSL_Integer llRound(double f)
-        {
-            m_host.AddScriptLPS(1);
-            return (int)Math.Round(f, MidpointRounding.AwayFromZero);
-        }
-
-        //This next group are vector operations involving squaring and square root. ckrinke
-        public LSL_Float llVecMag(LSL_Vector v)
-        {
-            m_host.AddScriptLPS(1);
-            return LSL_Vector.Mag(v);
-        }
-
-        public LSL_Vector llVecNorm(LSL_Vector v)
-        {
-            m_host.AddScriptLPS(1);
-            return LSL_Vector.Norm(v);
-        }
-
-        private double VecDist(LSL_Vector a, LSL_Vector b)
-        {
-            double dx = a.x - b.x;
-            double dy = a.y - b.y;
-            double dz = a.z - b.z;
-            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
-        }
-
-        public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
-        {
-            m_host.AddScriptLPS(1);
-            return VecDist(a, b);
-        }
-
-        //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
-
-        /// 
-        /// Convert an LSL rotation to a Euler vector.
-        /// 
-        /// 
-        /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
-        /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
-        /// 
-        /// 
-        /// 
-        public LSL_Vector llRot2Euler(LSL_Rotation r)
-        {
-            m_host.AddScriptLPS(1);
-
-            LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r;   // Z axis unit vector unaffected by Z rotation component of r.
-            double m = LSL_Vector.Mag(v);                       // Just in case v isn't normalized, need magnitude for Asin() operation later.
-            if (m == 0.0) return new LSL_Vector();
-            double x = Math.Atan2(-v.y, v.z);
-            double sin = v.x / m;
-            if (sin < -0.999999 || sin > 0.999999) x = 0.0;     // Force X rotation to 0 at the singularities.
-            double y = Math.Asin(sin);
-            // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
-            v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0)));
-            double z = Math.Atan2(v.y, v.x);
-
-            return new LSL_Vector(x, y, z);
-        }
-
-        /* From wiki:
-        The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
-        in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
-        a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
-        vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
-        */
-
-        /* How we arrived at this llEuler2Rot
-         *
-         * Experiment in SL to determine conventions:
-         *   llEuler2Rot()=<1,0,0,0>
-         *   llEuler2Rot(<0,PI,0>)=<0,1,0,0>
-         *   llEuler2Rot(<0,0,PI>)=<0,0,1,0>
-         *
-         * Important facts about Quaternions
-         *  - multiplication is non-commutative (a*b != b*a)
-         *  - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
-         *
-         * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
-         *   Qx = c1+i*s1
-         *   Qy = c2+j*s2;
-         *   Qz = c3+k*s3;
-         *
-         * Rotations applied in order (from above) Z, Y, X
-         * Q = (Qz * Qy) * Qx
-         * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
-         * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
-         * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
-         * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
-         * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3   -s1*s2*s3
-         * regroup: x=i*(s1*c2*c3+c1*s2*s3)
-         *          y=j*(c1*s2*c3-s1*c2*s3)
-         *          z=k*(s1*s2*c3+c1*c2*s3)
-         *          s=   c1*c2*c3-s1*s2*s3
-         *
-         * This implementation agrees with the functions found here:
-         * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
-         * And with the results in SL.
-         *
-         * It's also possible to calculate llEuler2Rot by direct multiplication of
-         * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
-         * from the wiki).
-         * Apparently in some cases this is better from a numerical precision perspective?
-         */
-
-        public LSL_Rotation llEuler2Rot(LSL_Vector v)
-        {
-            m_host.AddScriptLPS(1);
-
-            double x,y,z,s;
-
-            double c1 = Math.Cos(v.x * 0.5);
-            double c2 = Math.Cos(v.y * 0.5);
-            double c3 = Math.Cos(v.z * 0.5);
-            double s1 = Math.Sin(v.x * 0.5);
-            double s2 = Math.Sin(v.y * 0.5);
-            double s3 = Math.Sin(v.z * 0.5);
-
-            x = s1 * c2 * c3 + c1 * s2 * s3;
-            y = c1 * s2 * c3 - s1 * c2 * s3;
-            z = s1 * s2 * c3 + c1 * c2 * s3;
-            s = c1 * c2 * c3 - s1 * s2 * s3;
-
-            return new LSL_Rotation(x, y, z, s);
-        }
-
-        public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
-        {
-            m_host.AddScriptLPS(1);
-            double s;
-            double tr = fwd.x + left.y + up.z + 1.0;
-
-            if (tr >= 1.0)
-            {
-                s = 0.5 / Math.Sqrt(tr);
-                return new LSL_Rotation(
-                        (left.z - up.y) * s,
-                        (up.x - fwd.z) * s,
-                        (fwd.y - left.x) * s,
-                        0.25 / s);
-            }
-            else
-            {
-                double max = (left.y > up.z) ? left.y : up.z;
-
-                if (max < fwd.x)
-                {
-                    s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
-                    double x = s * 0.5;
-                    s = 0.5 / s;
-                    return new LSL_Rotation(
-                            x,
-                            (fwd.y + left.x) * s,
-                            (up.x + fwd.z) * s,
-                            (left.z - up.y) * s);
-                }
-                else if (max == left.y)
-                {
-                    s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
-                    double y = s * 0.5;
-                    s = 0.5 / s;
-                    return new LSL_Rotation(
-                            (fwd.y + left.x) * s,
-                            y,
-                            (left.z + up.y) * s,
-                            (up.x - fwd.z) * s);
-                }
-                else
-                {
-                    s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
-                    double z = s * 0.5;
-                    s = 0.5 / s;
-                    return new LSL_Rotation(
-                            (up.x + fwd.z) * s,
-                            (left.z + up.y) * s,
-                            z,
-                            (fwd.y - left.x) * s);
-                }
-            }
-        }
-
-        public LSL_Vector llRot2Fwd(LSL_Rotation r)
-        {
-            m_host.AddScriptLPS(1);
-
-            double x, y, z, m;
-
-            m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
-            // m is always greater than zero
-            // if m is not equal to 1 then Rotation needs to be normalized
-            if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
-            {
-                m = 1.0 / Math.Sqrt(m);
-                r.x *= m;
-                r.y *= m;
-                r.z *= m;
-                r.s *= m;
-            }
-
-            // Fast Algebric Calculations instead of Vectors & Quaternions Product
-            x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
-            y = 2 * (r.x * r.y + r.z * r.s);
-            z = 2 * (r.x * r.z - r.y * r.s);
-            return (new LSL_Vector(x, y, z));
-        }
-
-        public LSL_Vector llRot2Left(LSL_Rotation r)
-        {
-            m_host.AddScriptLPS(1);
-
-            double x, y, z, m;
-
-            m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
-            // m is always greater than zero
-            // if m is not equal to 1 then Rotation needs to be normalized
-            if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
-            {
-                m = 1.0 / Math.Sqrt(m);
-                r.x *= m;
-                r.y *= m;
-                r.z *= m;
-                r.s *= m;
-            }
-
-            // Fast Algebric Calculations instead of Vectors & Quaternions Product
-            x = 2 * (r.x * r.y - r.z * r.s);
-            y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
-            z = 2 * (r.x * r.s + r.y * r.z);
-            return (new LSL_Vector(x, y, z));
-        }
-
-        public LSL_Vector llRot2Up(LSL_Rotation r)
-        {
-            m_host.AddScriptLPS(1);
-            double x, y, z, m;
-
-            m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
-            // m is always greater than zero
-            // if m is not equal to 1 then Rotation needs to be normalized
-            if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
-            {
-                m = 1.0 / Math.Sqrt(m);
-                r.x *= m;
-                r.y *= m;
-                r.z *= m;
-                r.s *= m;
-            }
-
-            // Fast Algebric Calculations instead of Vectors & Quaternions Product
-            x = 2 * (r.x * r.z + r.y * r.s);
-            y = 2 * (-r.x * r.s + r.y * r.z);
-            z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
-            return (new LSL_Vector(x, y, z));
-        }
-
-        public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
-        {
-            //A and B should both be normalized
-            m_host.AddScriptLPS(1);
-            LSL_Rotation rotBetween;
-            // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
-            // continue calculation.
-            if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
-            {
-                rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
-            }
-            else
-            {
-                a = LSL_Vector.Norm(a);
-                b = LSL_Vector.Norm(b);
-                double dotProduct = LSL_Vector.Dot(a, b);
-                // There are two degenerate cases possible. These are for vectors 180 or
-                // 0 degrees apart. These have to be detected and handled individually.
-                //
-                // Check for vectors 180 degrees apart.
-                // A dot product of -1 would mean the angle between vectors is 180 degrees.
-                if (dotProduct < -0.9999999f)
-                {
-                    // First assume X axis is orthogonal to the vectors.
-                    LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
-                    orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
-                    // Check for near zero vector. A very small non-zero number here will create
-                    // a rotation in an undesired direction.
-                    if (LSL_Vector.Mag(orthoVector) > 0.0001)
-                    {
-                        rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f);
-                    }
-                    // If the magnitude of the vector was near zero, then assume the X axis is not
-                    // orthogonal and use the Z axis instead.
-                    else
-                    {
-                        // Set 180 z rotation.
-                        rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
-                    }
-                }
-                // Check for parallel vectors.
-                // A dot product of 1 would mean the angle between vectors is 0 degrees.
-                else if (dotProduct > 0.9999999f)
-                {
-                    // Set zero rotation.
-                    rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
-                }
-                else
-                {
-                    // All special checks have been performed so get the axis of rotation.
-                    LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
-                    // Quarternion s value is the length of the unit vector + dot product.
-                    double qs = 1.0 + dotProduct;
-                    rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
-                    // Normalize the rotation.
-                    double mag = LSL_Rotation.Mag(rotBetween);
-                    // We shouldn't have to worry about a divide by zero here. The qs value will be
-                    // non-zero because we already know if we're here, then the dotProduct is not -1 so
-                    // qs will not be zero. Also, we've already handled the input vectors being zero so the
-                    // crossProduct vector should also not be zero.
-                    rotBetween.x = rotBetween.x / mag;
-                    rotBetween.y = rotBetween.y / mag;
-                    rotBetween.z = rotBetween.z / mag;
-                    rotBetween.s = rotBetween.s / mag;
-                    // Check for undefined values and set zero rotation if any found. This code might not actually be required
-                    // any longer since zero vectors are checked for at the top.
-                    if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
-                    {
-                        rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
-                    }
-                }
-            }
-            return rotBetween;
-        }
-
-        public void llWhisper(int channelID, string text)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (text.Length > 1023)
-                text = text.Substring(0, 1023);
-
-            World.SimChat(Utils.StringToBytes(text),
-                          ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
-
-            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-            if (wComm != null)
-                wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
-        }
-
-        public void llSay(int channelID, string text)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
-            {
-                Console.WriteLine(text);
-            }
-            else
-            {
-                if (text.Length > 1023)
-                    text = text.Substring(0, 1023);
-
-                World.SimChat(Utils.StringToBytes(text),
-                              ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
-
-                IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-                if (wComm != null)
-                    wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
-            }
-        }
-
-        public void llShout(int channelID, string text)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (text.Length > 1023)
-                text = text.Substring(0, 1023);
-
-            World.SimChat(Utils.StringToBytes(text),
-                          ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
-
-            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-            if (wComm != null)
-                wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
-        }
-
-        public void llRegionSay(int channelID, string text)
-        {
-            if (channelID == 0)
-            {
-                Error("llRegionSay", "Cannot use on channel 0");
-                return;
-            }
-
-            if (text.Length > 1023)
-                text = text.Substring(0, 1023);
-
-            m_host.AddScriptLPS(1);
-
-            World.SimChat(Utils.StringToBytes(text),
-                          ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
-
-            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-            if (wComm != null)
-                wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
-        }
-
-        public void  llRegionSayTo(string target, int channel, string msg)
-        {
-            if (msg.Length > 1023)
-                msg = msg.Substring(0, 1023);
-
-            m_host.AddScriptLPS(1);
-
-            if (channel == ScriptBaseClass.DEBUG_CHANNEL)
-            {
-                return;
-            }
-
-            UUID TargetID;
-            UUID.TryParse(target, out TargetID);
-
-            World.SimChatToAgent(TargetID, Utils.StringToBytes(msg),
-                          channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
-
-            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-            if (wComm != null)
-                wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
-        }
-
-        public LSL_Integer llListen(int channelID, string name, string ID, string msg)
-        {
-            m_host.AddScriptLPS(1);
-            UUID keyID;
-            UUID.TryParse(ID, out keyID);
-            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-            if (wComm != null)
-                return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg);
-            else
-                return -1;
-        }
-
-        public void llListenControl(int number, int active)
-        {
-            m_host.AddScriptLPS(1);
-            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-            if (wComm != null)
-                wComm.ListenControl(m_item.ItemID, number, active);
-        }
-
-        public void llListenRemove(int number)
-        {
-            m_host.AddScriptLPS(1);
-            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
-            if (wComm != null)
-                wComm.ListenRemove(m_item.ItemID, number);
-        }
-
-        public void llSensor(string name, string id, int type, double range, double arc)
-        {
-            m_host.AddScriptLPS(1);
-            UUID keyID = UUID.Zero;
-            UUID.TryParse(id, out keyID);
-
-            AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host);
-       }
-
-        public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
-        {
-            m_host.AddScriptLPS(1);
-            UUID keyID = UUID.Zero;
-            UUID.TryParse(id, out keyID);
-
-            AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host);
-        }
-
-        public void llSensorRemove()
-        {
-            m_host.AddScriptLPS(1);
-            AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID);
-        }
-
-        public string resolveName(UUID objecUUID)
-        {
-            // try avatar username surname
-            UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID);
-            if (account != null)
-            {
-                string avatarname = account.Name;
-                return avatarname;
-            }
-            // try an scene object
-            SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
-            if (SOP != null)
-            {
-                string objectname = SOP.Name;
-                return objectname;
-            }
-
-            EntityBase SensedObject;
-            World.Entities.TryGetValue(objecUUID, out SensedObject);
-
-            if (SensedObject == null)
-            {
-                IGroupsModule groups = World.RequestModuleInterface();
-                if (groups != null)
-                {
-                    GroupRecord gr = groups.GetGroupRecord(objecUUID);
-                    if (gr != null)
-                        return gr.GroupName;
-                }
-                return String.Empty;
-            }
-
-            return SensedObject.Name;
-        }
-
-        public LSL_String llDetectedName(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return String.Empty;
-            return detectedParams.Name;
-        }
-
-        public LSL_String llDetectedKey(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return String.Empty;
-            return detectedParams.Key.ToString();
-        }
-
-        public LSL_String llDetectedOwner(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return String.Empty;
-            return detectedParams.Owner.ToString();
-        }
-
-        public LSL_Integer llDetectedType(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return 0;
-            return new LSL_Integer(detectedParams.Type);
-        }
-
-        public LSL_Vector llDetectedPos(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return new LSL_Vector();
-            return detectedParams.Position;
-        }
-
-        public LSL_Vector llDetectedVel(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return new LSL_Vector();
-            return detectedParams.Velocity;
-        }
-
-        public LSL_Vector llDetectedGrab(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (parms == null)
-                return new LSL_Vector(0, 0, 0);
-
-            return parms.OffsetPos;
-        }
-
-        public LSL_Rotation llDetectedRot(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return new LSL_Rotation();
-            return detectedParams.Rotation;
-        }
-
-        public LSL_Integer llDetectedGroup(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (detectedParams == null)
-                return new LSL_Integer(0);
-            if (m_host.GroupID == detectedParams.Group)
-                return new LSL_Integer(1);
-            return new LSL_Integer(0);
-        }
-
-        public LSL_Integer llDetectedLinkNumber(int number)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
-            if (parms == null)
-                return new LSL_Integer(0);
-
-            return new LSL_Integer(parms.LinkNum);
-        }
-
-        /// 
-        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
-        /// 
-        public LSL_Vector llDetectedTouchBinormal(int index)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
-            if (detectedParams == null)
-                return new LSL_Vector();
-            return detectedParams.TouchBinormal;
-        }
-
-        /// 
-        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
-        /// 
-        public LSL_Integer llDetectedTouchFace(int index)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
-            if (detectedParams == null)
-                return new LSL_Integer(-1);
-            return new LSL_Integer(detectedParams.TouchFace);
-        }
-
-        /// 
-        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
-        /// 
-        public LSL_Vector llDetectedTouchNormal(int index)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
-            if (detectedParams == null)
-                return new LSL_Vector();
-            return detectedParams.TouchNormal;
-        }
-
-        /// 
-        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
-        /// 
-        public LSL_Vector llDetectedTouchPos(int index)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
-            if (detectedParams == null)
-                return new LSL_Vector();
-            return detectedParams.TouchPos;
-        }
-
-        /// 
-        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
-        /// 
-        public LSL_Vector llDetectedTouchST(int index)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
-            if (detectedParams == null)
-                return new LSL_Vector(-1.0, -1.0, 0.0);
-            return detectedParams.TouchST;
-        }
-
-        /// 
-        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
-        /// 
-        public LSL_Vector llDetectedTouchUV(int index)
-        {
-            m_host.AddScriptLPS(1);
-            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
-            if (detectedParams == null)
-                return new LSL_Vector(-1.0, -1.0, 0.0);
-            return detectedParams.TouchUV;
-        }
-
-        public virtual void llDie()
-        {
-            m_host.AddScriptLPS(1);
-            throw new SelfDeleteException();
-        }
-
-        public LSL_Float llGround(LSL_Vector offset)
-        {
-            m_host.AddScriptLPS(1);
-            Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
-
-            //Get the slope normal.  This gives us the equation of the plane tangent to the slope.
-            LSL_Vector vsn = llGroundNormal(offset);
-
-            // Clamp to valid position
-            if (pos.X < 0)
-                pos.X = 0;
-            else if (pos.X >= World.Heightmap.Width)
-                pos.X = World.Heightmap.Width - 1;
-            if (pos.Y < 0)
-                pos.Y = 0;
-            else if (pos.Y >= World.Heightmap.Height)
-                pos.Y = World.Heightmap.Height - 1;
-
-            //Get the height for the integer coordinates from the Heightmap
-            float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y];
-
-            //Calculate the difference between the actual coordinates and the integer coordinates
-            float xdiff = pos.X - (float)((int)pos.X);
-            float ydiff = pos.Y - (float)((int)pos.Y);
-
-            //Use the equation of the tangent plane to adjust the height to account for slope
-
-            return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight;
-        }
-
-        public LSL_Float llCloud(LSL_Vector offset)
-        {
-            m_host.AddScriptLPS(1);
-            float cloudCover = 0f;
-            ICloudModule module = World.RequestModuleInterface();
-            if (module != null)
-            {
-                Vector3 pos = m_host.GetWorldPosition();
-                int x = (int)(pos.X + offset.x);
-                int y = (int)(pos.Y + offset.y);
-
-                cloudCover = module.CloudCover(x, y, 0);
-
-            }
-            return cloudCover;
-        }
-
-        public LSL_Vector llWind(LSL_Vector offset)
-        {
-            m_host.AddScriptLPS(1);
-            LSL_Vector wind = new LSL_Vector(0, 0, 0);
-            IWindModule module = World.RequestModuleInterface();
-            if (module != null)
-            {
-                Vector3 pos = m_host.GetWorldPosition();
-                int x = (int)(pos.X + offset.x);
-                int y = (int)(pos.Y + offset.y);
-
-                Vector3 windSpeed = module.WindSpeed(x, y, 0);
-
-                wind.x = windSpeed.X;
-                wind.y = windSpeed.Y;
-            }
-            return wind;
-        }
-
-        public void llSetStatus(int status, int value)
-        {
-            m_host.AddScriptLPS(1);
-
-            int statusrotationaxis = 0;
-
-            if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
-            {
-                if (value != 0)
-                {
-                    SceneObjectGroup group = m_host.ParentGroup;
-                    bool allow = true;
-
-                    foreach (SceneObjectPart part in group.Parts)
-                    {
-                        if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
-                        {
-                            allow = false;
-                            break;
-                        }
-                    }
-
-                    if (!allow)
-                        return;
-
-                    m_host.ScriptSetPhysicsStatus(true);
-                }
-                else
-                {
-                    m_host.ScriptSetPhysicsStatus(false);
-                }
-            }
-
-            if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
-            {
-                m_host.ParentGroup.ScriptSetPhantomStatus(value != 0);
-            }
-
-            if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
-            {
-                m_host.AddFlag(PrimFlags.CastShadows);
-            }
-
-            if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
-            {
-                statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
-            }
-
-            if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
-            {
-                statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
-            }
-
-            if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
-            {
-                statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
-            }
-
-            if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
-                m_host.BlockGrab = value != 0;
-
-            if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
-                m_host.ParentGroup.BlockGrabOverride = value != 0;
-
-            if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
-            {
-                if (value != 0)
-                    m_host.SetDieAtEdge(true);
-                else
-                    m_host.SetDieAtEdge(false);
-            }
-
-            if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
-            {
-                if (value != 0)
-                    m_host.SetReturnAtEdge(true);
-                else
-                    m_host.SetReturnAtEdge(false);
-            }
-
-            if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
-            {
-                if (value != 0)
-                    m_host.SetStatusSandbox(true);
-                else
-                    m_host.SetStatusSandbox(false);
-            }
-
-            if (statusrotationaxis != 0)
-            {
-                m_host.SetAxisRotation(statusrotationaxis, value);
-            }
-        }
-
-        private bool IsPhysical()
-        {
-            return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics);
-        }
-
-        public LSL_Integer llGetStatus(int status)
-        {
-            m_host.AddScriptLPS(1);
-            // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
-            switch (status)
-            {
-                case ScriptBaseClass.STATUS_PHYSICS:
-                    return IsPhysical() ? 1 : 0;
-
-                case ScriptBaseClass.STATUS_PHANTOM:
-                    if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
-                    {
-                        return 1;
-                    }
-                    return 0;
-
-                case ScriptBaseClass.STATUS_CAST_SHADOWS:
-                    if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
-                    {
-                        return 1;
-                    }
-                    return 0;
-
-                case ScriptBaseClass.STATUS_BLOCK_GRAB:
-                    return m_host.BlockGrab ? 1 : 0;
-
-                case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT:
-                    return m_host.ParentGroup.BlockGrabOverride ? 1 : 0;
-
-                case ScriptBaseClass.STATUS_DIE_AT_EDGE:
-                    if (m_host.GetDieAtEdge())
-                        return 1;
-                    else
-                        return 0;
-
-                case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
-                    if (m_host.GetReturnAtEdge())
-                        return 1;
-                    else
-                        return 0;
-
-                case ScriptBaseClass.STATUS_ROTATE_X:
-                    // if (m_host.GetAxisRotation(2) != 0)
-                    if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
-                        return 1;
-                    else
-                        return 0;
-
-                case ScriptBaseClass.STATUS_ROTATE_Y:
-                    if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
-                        return 1;
-                    else
-                        return 0;
-
-                case ScriptBaseClass.STATUS_ROTATE_Z:
-                    if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
-                        return 1;
-                    else
-                        return 0;
-
-                case ScriptBaseClass.STATUS_SANDBOX:
-                    if (m_host.GetStatusSandbox())
-                        return 1;
-                    else
-                        return 0;
-            }
-            return 0;
-        }
-
-        public void llSetScale(LSL_Vector scale)
-        {
-            m_host.AddScriptLPS(1);
-            SetScale(m_host, scale);
-        }
-
-        protected void SetScale(SceneObjectPart part, LSL_Vector scale)
-        {
-            // TODO: this needs to trigger a persistance save as well
-            if (part == null || part.ParentGroup.IsDeleted)
-                return;
-
-            // First we need to check whether or not we need to clamp the size of a physics-enabled prim
-            PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
-            if (pa != null && pa.IsPhysical)
-            {
-                scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
-                scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
-                scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
-            }
-            else
-            {
-                // If not physical, then we clamp the scale to the non-physical min/max
-                scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
-                scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
-                scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
-            }
-
-            Vector3 tmp = part.Scale;
-            tmp.X = (float)scale.x;
-            tmp.Y = (float)scale.y;
-            tmp.Z = (float)scale.z;
-            part.Scale = tmp;
-            part.SendFullUpdateToAllClients();
-        }
-
-        public LSL_Vector llGetScale()
-        {
-            m_host.AddScriptLPS(1);
-            return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
-        }
-
-        public void llSetClickAction(int action)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.ClickAction = (byte)action;
-            m_host.ParentGroup.HasGroupChanged = true;
-            m_host.ScheduleFullUpdate();
-            return;
-        }
-
-        public void llSetColor(LSL_Vector color, int face)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (face == ScriptBaseClass.ALL_SIDES)
-                face = SceneObjectPart.ALL_SIDES;
-
-            m_host.SetFaceColorAlpha(face, color, null);
-        }
-
-        public void llSetContentType(LSL_Key id, LSL_Integer type)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_UrlModule == null)
-                return;
-
-            // Make sure the content type is text/plain to start with
-            m_UrlModule.HttpContentType(new UUID(id), "text/plain");
-
-            // Is the object owner online and in the region
-            ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID);
-            if (agent == null || agent.IsChildAgent)
-                return;  // Fail if the owner is not in the same region
-
-            // Is it the embeded browser?
-            string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
-            if (userAgent.IndexOf("SecondLife") < 0)
-                return; // Not the embedded browser. Is this check good enough?
-
-            // Use the IP address of the client and check against the request
-            // seperate logins from the same IP will allow all of them to get non-text/plain as long
-            // as the owner is in the region. Same as SL!
-            string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString();
-            string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr");
-            //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'");
-            if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "")
-                return;
-            if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "")
-                return;
-
-            // If the request isnt from the same IP address then the request cannot be from the owner
-            if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim()))
-                return;
-
-            switch (type)
-            {
-                case ScriptBaseClass.CONTENT_TYPE_HTML:
-                    m_UrlModule.HttpContentType(new UUID(id), "text/html");
-                    break;
-                case ScriptBaseClass.CONTENT_TYPE_XML:
-                    m_UrlModule.HttpContentType(new UUID(id), "application/xml");
-                    break;
-                case ScriptBaseClass.CONTENT_TYPE_XHTML:
-                    m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml");
-                    break;
-                case ScriptBaseClass.CONTENT_TYPE_ATOM:
-                    m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml");
-                    break;
-                case ScriptBaseClass.CONTENT_TYPE_JSON:
-                    m_UrlModule.HttpContentType(new UUID(id), "application/json");
-                    break;
-                case ScriptBaseClass.CONTENT_TYPE_LLSD:
-                    m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml");
-                    break;
-                case ScriptBaseClass.CONTENT_TYPE_FORM:
-                    m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded");
-                    break;
-                case ScriptBaseClass.CONTENT_TYPE_RSS:
-                    m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml");
-                    break;
-                default:
-                    m_UrlModule.HttpContentType(new UUID(id), "text/plain");
-                    break;
-            }
-        }
-
-        public void SetTexGen(SceneObjectPart part, int face,int style)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            MappingType textype;
-            textype = MappingType.Default;
-            if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
-                textype = MappingType.Planar;
-
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                tex.CreateFace((uint) face);
-                tex.FaceTextures[face].TexMapType = textype;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            else if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (uint i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        tex.FaceTextures[i].TexMapType = textype;
-                    }
-                    tex.DefaultTexture.TexMapType = textype;
-                }
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        public void SetGlow(SceneObjectPart part, int face, float glow)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                tex.CreateFace((uint) face);
-                tex.FaceTextures[face].Glow = glow;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            else if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (uint i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        tex.FaceTextures[i].Glow = glow;
-                    }
-                    tex.DefaultTexture.Glow = glow;
-                }
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
-        {
-
-            Shininess sval = new Shininess();
-
-            switch (shiny)
-            {
-            case 0:
-                sval = Shininess.None;
-                break;
-            case 1:
-                sval = Shininess.Low;
-                break;
-            case 2:
-                sval = Shininess.Medium;
-                break;
-            case 3:
-                sval = Shininess.High;
-                break;
-            default:
-                sval = Shininess.None;
-                break;
-            }
-
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                tex.CreateFace((uint) face);
-                tex.FaceTextures[face].Shiny = sval;
-                tex.FaceTextures[face].Bump = bump;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            else if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (uint i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        tex.FaceTextures[i].Shiny = sval;
-                        tex.FaceTextures[i].Bump = bump;
-                    }
-                    tex.DefaultTexture.Shiny = sval;
-                    tex.DefaultTexture.Bump = bump;
-                }
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        public void SetFullBright(SceneObjectPart part, int face, bool bright)
-        {
-             Primitive.TextureEntry tex = part.Shape.Textures;
-             if (face >= 0 && face < GetNumberOfSides(part))
-             {
-                 tex.CreateFace((uint) face);
-                 tex.FaceTextures[face].Fullbright = bright;
-                 part.UpdateTextureEntry(tex.GetBytes());
-                 return;
-             }
-             else if (face == ScriptBaseClass.ALL_SIDES)
-             {
-                 for (uint i = 0; i < GetNumberOfSides(part); i++)
-                 {
-                     if (tex.FaceTextures[i] != null)
-                     {
-                         tex.FaceTextures[i].Fullbright = bright;
-                     }
-                 }
-                 tex.DefaultTexture.Fullbright = bright;
-                 part.UpdateTextureEntry(tex.GetBytes());
-                 return;
-             }
-         }
-
-        public LSL_Float llGetAlpha(int face)
-        {
-            m_host.AddScriptLPS(1);
-
-            return GetAlpha(m_host, face);
-        }
-
-        protected LSL_Float GetAlpha(SceneObjectPart part, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                int i;
-                double sum = 0.0;
-                for (i = 0 ; i < GetNumberOfSides(part); i++)
-                    sum += (double)tex.GetFace((uint)i).RGBA.A;
-                return sum;
-            }
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                return (double)tex.GetFace((uint)face).RGBA.A;
-            }
-            return 0.0;
-        }
-
-        public void llSetAlpha(double alpha, int face)
-        {
-            m_host.AddScriptLPS(1);
-
-            SetAlpha(m_host, alpha, face);
-        }
-
-        public void llSetLinkAlpha(int linknumber, double alpha, int face)
-        {
-            m_host.AddScriptLPS(1);
-
-            List parts = GetLinkParts(linknumber);
-
-            foreach (SceneObjectPart part in parts)
-                SetAlpha(part, alpha, face);
-        }
-
-        protected void SetAlpha(SceneObjectPart part, double alpha, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            Color4 texcolor;
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                texcolor = tex.CreateFace((uint)face).RGBA;
-                texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
-                tex.FaceTextures[face].RGBA = texcolor;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            else if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (int i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        texcolor = tex.FaceTextures[i].RGBA;
-                        texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
-                        tex.FaceTextures[i].RGBA = texcolor;
-                    }
-                }
-
-                // In some cases, the default texture can be null, eg when every face
-                // has a unique texture
-                if (tex.DefaultTexture != null)
-                {
-                    texcolor = tex.DefaultTexture.RGBA;
-                    texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
-                    tex.DefaultTexture.RGBA = texcolor;
-                }
-
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        /// 
-        /// Set flexi parameters of a part.
-        ///
-        /// FIXME: Much of this code should probably be within the part itself.
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
-            float wind, float tension, LSL_Vector Force)
-        {
-            if (part == null)
-                return;
-
-            if (flexi)
-            {
-                part.Shape.FlexiEntry = true;   // this setting flexi true isn't working, but the below parameters do
-                                                                // work once the prim is already flexi
-                part.Shape.FlexiSoftness = softness;
-                part.Shape.FlexiGravity = gravity;
-                part.Shape.FlexiDrag = friction;
-                part.Shape.FlexiWind = wind;
-                part.Shape.FlexiTension = tension;
-                part.Shape.FlexiForceX = (float)Force.x;
-                part.Shape.FlexiForceY = (float)Force.y;
-                part.Shape.FlexiForceZ = (float)Force.z;
-                part.Shape.PathCurve = (byte)Extrusion.Flexible;
-            }
-            else
-            {
-                // Other values not set, they do not seem to be sent to the viewer
-                // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off
-                part.Shape.PathCurve = (byte)Extrusion.Straight;
-                part.Shape.FlexiEntry = false;
-            }
-            part.ParentGroup.HasGroupChanged = true;
-            part.ScheduleFullUpdate();
-        }
-
-        /// 
-        /// Set a light point on a part
-        /// 
-        /// FIXME: Much of this code should probably be in SceneObjectGroup
-        ///
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
-        {
-            if (part == null)
-                return;
-
-            if (light)
-            {
-                part.Shape.LightEntry = true;
-                part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
-                part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
-                part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
-                part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f);
-                part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f);
-                part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f);
-            }
-            else
-            {
-                part.Shape.LightEntry = false;
-            }
-
-            part.ParentGroup.HasGroupChanged = true;
-            part.ScheduleFullUpdate();
-        }
-
-        public LSL_Vector llGetColor(int face)
-        {
-            m_host.AddScriptLPS(1);
-            return GetColor(m_host, face);
-        }
-
-        protected LSL_Vector GetColor(SceneObjectPart part, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            Color4 texcolor;
-            LSL_Vector rgb = new LSL_Vector();
-            if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                int i;
-
-                for (i = 0 ; i < GetNumberOfSides(part); i++)
-                {
-                    texcolor = tex.GetFace((uint)i).RGBA;
-                    rgb.x += texcolor.R;
-                    rgb.y += texcolor.G;
-                    rgb.z += texcolor.B;
-                }
-
-                rgb.x /= (float)GetNumberOfSides(part);
-                rgb.y /= (float)GetNumberOfSides(part);
-                rgb.z /= (float)GetNumberOfSides(part);
-
-                return rgb;
-            }
-
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                texcolor = tex.GetFace((uint)face).RGBA;
-                rgb.x = texcolor.R;
-                rgb.y = texcolor.G;
-                rgb.z = texcolor.B;
-
-                return rgb;
-            }
-            else
-            {
-                return new LSL_Vector();
-            }
-        }
-
-        public void llSetTexture(string texture, int face)
-        {
-            m_host.AddScriptLPS(1);
-            SetTexture(m_host, texture, face);
-            ScriptSleep(m_sleepMsOnSetTexture);
-        }
-
-        public void llSetLinkTexture(int linknumber, string texture, int face)
-        {
-            m_host.AddScriptLPS(1);
-
-            List parts = GetLinkParts(linknumber);
-
-            foreach (SceneObjectPart part in parts)
-              SetTexture(part, texture, face);
-
-            ScriptSleep(m_sleepMsOnSetLinkTexture);
-        }
-
-        protected void SetTexture(SceneObjectPart part, string texture, int face)
-        {
-            UUID textureID = new UUID();
-
-            textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
-            if (textureID == UUID.Zero)
-            {
-                if (!UUID.TryParse(texture, out textureID))
-                    return;
-            }
-
-            Primitive.TextureEntry tex = part.Shape.Textures;
-
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
-                texface.TextureID = textureID;
-                tex.FaceTextures[face] = texface;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            else if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (uint i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        tex.FaceTextures[i].TextureID = textureID;
-                    }
-                }
-                tex.DefaultTexture.TextureID = textureID;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        public void llScaleTexture(double u, double v, int face)
-        {
-            m_host.AddScriptLPS(1);
-
-            ScaleTexture(m_host, u, v, face);
-            ScriptSleep(m_sleepMsOnScaleTexture);
-        }
-
-        protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
-                texface.RepeatU = (float)u;
-                texface.RepeatV = (float)v;
-                tex.FaceTextures[face] = texface;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (int i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        tex.FaceTextures[i].RepeatU = (float)u;
-                        tex.FaceTextures[i].RepeatV = (float)v;
-                    }
-                }
-                tex.DefaultTexture.RepeatU = (float)u;
-                tex.DefaultTexture.RepeatV = (float)v;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        public void llOffsetTexture(double u, double v, int face)
-        {
-            m_host.AddScriptLPS(1);
-            OffsetTexture(m_host, u, v, face);
-            ScriptSleep(m_sleepMsOnOffsetTexture);
-        }
-
-        protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
-                texface.OffsetU = (float)u;
-                texface.OffsetV = (float)v;
-                tex.FaceTextures[face] = texface;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (int i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        tex.FaceTextures[i].OffsetU = (float)u;
-                        tex.FaceTextures[i].OffsetV = (float)v;
-                    }
-                }
-                tex.DefaultTexture.OffsetU = (float)u;
-                tex.DefaultTexture.OffsetV = (float)v;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        public void llRotateTexture(double rotation, int face)
-        {
-            m_host.AddScriptLPS(1);
-            RotateTexture(m_host, rotation, face);
-            ScriptSleep(m_sleepMsOnRotateTexture);
-        }
-
-        protected void RotateTexture(SceneObjectPart part, double rotation, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
-                texface.Rotation = (float)rotation;
-                tex.FaceTextures[face] = texface;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-            if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                for (int i = 0; i < GetNumberOfSides(part); i++)
-                {
-                    if (tex.FaceTextures[i] != null)
-                    {
-                        tex.FaceTextures[i].Rotation = (float)rotation;
-                    }
-                }
-                tex.DefaultTexture.Rotation = (float)rotation;
-                part.UpdateTextureEntry(tex.GetBytes());
-                return;
-            }
-        }
-
-        public LSL_String llGetTexture(int face)
-        {
-            m_host.AddScriptLPS(1);
-            return GetTexture(m_host, face);
-        }
-
-        protected LSL_String GetTexture(SceneObjectPart part, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                face = 0;
-            }
-
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                Primitive.TextureEntryFace texface;
-                texface = tex.GetFace((uint)face);
-                string texture = texface.TextureID.ToString();
-
-                lock (part.TaskInventory)
-                {
-                    foreach (KeyValuePair inv in part.TaskInventory)
-                    {
-                        if (inv.Value.AssetID == texface.TextureID)
-                        {
-                            texture = inv.Value.Name.ToString();
-                            break;
-                        }
-                    }
-                }
-
-                return texture;
-            }
-            else
-            {
-                return UUID.Zero.ToString();
-            }
-        }
-
-        public void llSetPos(LSL_Vector pos)
-        {
-            m_host.AddScriptLPS(1);
-
-            SetPos(m_host, pos, true);
-
-            ScriptSleep(m_sleepMsOnSetPos);
-        }
-
-        /// 
-        /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos
-        /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into.
-        /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking.
-        /// 
-        /// 
-        /// 1 if successful, 0 otherwise.
-        public LSL_Integer llSetRegionPos(LSL_Vector pos)
-        {
-            m_host.AddScriptLPS(1);
-
-            // BEGIN WORKAROUND
-            // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
-            //
-            // This workaround is to prevent silent failure of this function.
-            // According to the specification on the SL Wiki, providing a position outside of the
-            if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
-            {
-                return 0;
-            }
-            // END WORK AROUND
-            else if ( // this is not part of the workaround if-block because it's not related to the workaround.
-                IsPhysical() ||
-                m_host.ParentGroup.IsAttachment || // return FALSE if attachment
-                (
-                    pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
-                    pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
-                    pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
-                    pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
-                    pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
-                )
-            )
-            {
-                return 0;
-            }
-
-            // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range.
-            // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
-
-            Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
-            LandData here = World.GetLandData(objectPos);
-            LandData there = World.GetLandData(pos);
-
-            // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
-
-            bool sameParcel = here.GlobalID == there.GlobalID;
-
-            if (!sameParcel && !World.Permissions.CanRezObject(
-                m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
-            {
-                return 0;
-            }
-
-            SetPos(m_host.ParentGroup.RootPart, pos, false);
-
-            return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0;
-        }
-
-        // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
-        // note linked setpos is capped "differently"
-        private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
-        {
-            if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor)
-                return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start);
-            else
-                return end;
-        }
-
-        protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos)
-        {
-            if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
-                return fromPos;
-
-            // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
-
-
-            float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
-            bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
-
-            if (part.ParentGroup.RootPart == part)
-            {
-                if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
-                    targetPos.z = ground;
-            }
-            LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos);
-
-            return real_vec;
-        }
-
-        /// 
-        /// set object position, optionally capping the distance.
-        /// 
-        /// 
-        /// 
-        /// if TRUE, will cap the distance to 10m.
-        protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
-        {
-            // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
-            LSL_Vector currentPos = GetPartLocalPos(part);
-
-            float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
-            bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
-
-            if (part.ParentGroup.RootPart == part)
-            {
-                if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
-                    targetPos.z = ground;
-                SceneObjectGroup parent = part.ParentGroup;
-                parent.UpdateGroupPosition(!adjust ? targetPos :
-                    SetPosAdjust(currentPos, targetPos));
-            }
-            else
-            {
-                part.OffsetPosition = !adjust ? targetPos :
-                    SetPosAdjust(currentPos, targetPos);
-                SceneObjectGroup parent = part.ParentGroup;
-                parent.HasGroupChanged = true;
-                parent.ScheduleGroupForTerseUpdate();
-            }
-        }
-
-        public LSL_Vector llGetPos()
-        {
-            m_host.AddScriptLPS(1);
-            return m_host.GetWorldPosition();
-        }
-
-        public LSL_Vector llGetLocalPos()
-        {
-            m_host.AddScriptLPS(1);
-            return GetPartLocalPos(m_host);
-        }
-
-        protected LSL_Vector GetPartLocalPos(SceneObjectPart part)
-        {
-            m_host.AddScriptLPS(1);
-
-            Vector3 pos;
-
-            if (!part.IsRoot)
-            {
-                pos = part.OffsetPosition;
-            }
-            else
-            {
-                if (part.ParentGroup.IsAttachment)
-                {
-                    pos = part.AttachedPos;
-                }
-                else
-                {
-                    pos = part.AbsolutePosition;
-                }
-            }
-
-//            m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
-
-            return new LSL_Vector(pos);
-        }
-
-        public void llSetRot(LSL_Rotation rot)
-        {
-            m_host.AddScriptLPS(1);
-
-            // try to let this work as in SL...
-            if (m_host.ParentID == 0)
-            {
-                // special case: If we are root, rotate complete SOG to new rotation
-                SetRot(m_host, rot);
-            }
-            else
-            {
-                // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
-                SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
-                if (rootPart != null) // better safe than sorry
-                {
-                    SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
-                }
-            }
-
-            ScriptSleep(m_sleepMsOnSetRot);
-        }
-
-        public void llSetLocalRot(LSL_Rotation rot)
-        {
-            m_host.AddScriptLPS(1);
-            SetRot(m_host, rot);
-            ScriptSleep(m_sleepMsOnSetLocalRot);
-        }
-
-        protected void SetRot(SceneObjectPart part, Quaternion rot)
-        {
-            part.UpdateRotation(rot);
-            // Update rotation does not move the object in the physics scene if it's a linkset.
-
-//KF:  Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type
-//          part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
-
-            // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
-            // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
-            // It's perfectly okay when the object is not an active physical body though.
-            // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
-            // but only if the object is not physial and active.   This is important for rotating doors.
-            // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
-            // scene
-            PhysicsActor pa = part.PhysActor;
-
-            if (pa != null && !pa.IsPhysical)
-            {
-                part.ParentGroup.ResetChildPrimPhysicsPositions();
-            }
-        }
-
-        /// 
-        /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
-        /// 
-        public LSL_Rotation llGetRot()
-        {
-            // unlinked or root prim then use llRootRotation
-            // see llRootRotaion for references.
-            if (m_host.LinkNum == 0 || m_host.LinkNum == 1)
-            {
-                return llGetRootRotation();
-            }
-
-            m_host.AddScriptLPS(1);
-            Quaternion q = m_host.GetWorldRotation();
-            return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
-        }
-
-        private LSL_Rotation GetPartRot(SceneObjectPart part)
-        {
-            Quaternion q;
-            if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim
-            {
-                if (part.ParentGroup.AttachmentPoint != 0)
-                {
-                    ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
-                    if (avatar != null)
-                    {
-                        if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
-                            q = avatar.CameraRotation; // Mouselook
-                        else
-                            q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
-                    }
-                    else
-                        q = part.ParentGroup.GroupRotation; // Likely never get here but just in case
-                }
-                else
-                    q = part.ParentGroup.GroupRotation; // just the group rotation
-
-                return new LSL_Rotation(q);
-            }
-
-            return new LSL_Rotation(part.GetWorldRotation());
-        }
-
-        public LSL_Rotation llGetLocalRot()
-        {
-            m_host.AddScriptLPS(1);
-
-            return new LSL_Rotation(m_host.RotationOffset);
-        }
-
-        public void llSetForce(LSL_Vector force, int local)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (!m_host.ParentGroup.IsDeleted)
-            {
-                if (local != 0)
-                    force *= llGetRot();
-
-                m_host.ParentGroup.RootPart.SetForce(force);
-            }
-        }
-
-        public LSL_Vector llGetForce()
-        {
-            LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
-
-            m_host.AddScriptLPS(1);
-
-            if (!m_host.ParentGroup.IsDeleted)
-            {
-                force = m_host.ParentGroup.RootPart.GetForce();
-            }
-
-            return force;
-        }
-
-        public void llSetVelocity(LSL_Vector velocity, int local)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (!m_host.ParentGroup.IsDeleted)
-            {
-                if (local != 0)
-                    velocity *= llGetRot();
-
-                m_host.ParentGroup.RootPart.Velocity = velocity;
-            }
-        }
-
-        public void llSetAngularVelocity(LSL_Vector angularVelocity, int local)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (!m_host.ParentGroup.IsDeleted)
-            {
-                if (local != 0)
-                    angularVelocity *= llGetRot();
-
-                m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity;
-            }
-        }
-
-        public LSL_Integer llTarget(LSL_Vector position, double range)
-        {
-            m_host.AddScriptLPS(1);
-            return m_host.ParentGroup.registerTargetWaypoint(position,
-                (float)range);
-        }
-
-        public void llTargetRemove(int number)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.ParentGroup.unregisterTargetWaypoint(number);
-        }
-
-        public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
-        {
-            m_host.AddScriptLPS(1);
-            return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
-        }
-
-        public void llRotTargetRemove(int number)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.ParentGroup.unregisterRotTargetWaypoint(number);
-        }
-
-        public void llMoveToTarget(LSL_Vector target, double tau)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.MoveToTarget(target, (float)tau);
-        }
-
-        public void llStopMoveToTarget()
-        {
-            m_host.AddScriptLPS(1);
-            m_host.StopMoveToTarget();
-        }
-
-        public void llApplyImpulse(LSL_Vector force, int local)
-        {
-            m_host.AddScriptLPS(1);
-            //No energy force yet
-            Vector3 v = force;
-            if (v.Length() > 20000.0f)
-            {
-                v.Normalize();
-                v = v * 20000.0f;
-            }
-            m_host.ApplyImpulse(v, local != 0);
-        }
-
-        public void llApplyRotationalImpulse(LSL_Vector force, int local)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.ApplyAngularImpulse(force, local != 0);
-        }
-
-        public void llSetTorque(LSL_Vector torque, int local)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.SetAngularImpulse(torque, local != 0);
-        }
-
-        public LSL_Vector llGetTorque()
-        {
-            m_host.AddScriptLPS(1);
-
-            return new LSL_Vector(m_host.ParentGroup.GetTorque());
-        }
-
-        public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
-        {
-            m_host.AddScriptLPS(1);
-            llSetForce(force, local);
-            llSetTorque(torque, local);
-        }
-
-        public LSL_Vector llGetVel()
-        {
-            m_host.AddScriptLPS(1);
-
-            Vector3 vel;
-
-            if (m_host.ParentGroup.IsAttachment)
-            {
-                ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
-                vel = avatar.GetWorldVelocity();
-            }
-            else
-            {
-                vel = m_host.Velocity;
-            }
-
-            return new LSL_Vector(vel);
-        }
-
-        public LSL_Vector llGetAccel()
-        {
-            m_host.AddScriptLPS(1);
-
-            return new LSL_Vector(m_host.Acceleration);
-        }
-
-        public LSL_Vector llGetOmega()
-        {
-            m_host.AddScriptLPS(1);
-
-            return new LSL_Vector(m_host.AngularVelocity);
-        }
-
-        public LSL_Float llGetTimeOfDay()
-        {
-            m_host.AddScriptLPS(1);
-            return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
-        }
-
-        public LSL_Float llGetWallclock()
-        {
-            m_host.AddScriptLPS(1);
-            return DateTime.Now.TimeOfDay.TotalSeconds;
-        }
-
-        public LSL_Float llGetTime()
-        {
-            m_host.AddScriptLPS(1);
-            TimeSpan ScriptTime = DateTime.Now - m_timer;
-            return (double)(ScriptTime.TotalMilliseconds / 1000);
-        }
-
-        public void llResetTime()
-        {
-            m_host.AddScriptLPS(1);
-            m_timer = DateTime.Now;
-        }
-
-        public LSL_Float llGetAndResetTime()
-        {
-            m_host.AddScriptLPS(1);
-            TimeSpan ScriptTime = DateTime.Now - m_timer;
-            m_timer = DateTime.Now;
-            return (double)(ScriptTime.TotalMilliseconds / 1000);
-        }
-
-        public void llSound(string sound, double volume, int queue, int loop)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llSound", "Use llPlaySound instead");
-        }
-
-        // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
-        // 20080530 Updated to remove code duplication
-        public void llPlaySound(string sound, double volume)
-        {
-            m_host.AddScriptLPS(1);
-
-            // send the sound, once, to all clients in range
-            if (m_SoundModule != null)
-            {
-                m_SoundModule.SendSound(
-                    m_host.UUID,
-                    ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), 
-                    volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
-                    0, false, false);
-            }
-        }
-
-        public void llLoopSound(string sound, double volume)
-        {
-            m_host.AddScriptLPS(1);
-            if (m_SoundModule != null)
-            {
-                m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
-                        volume, 20, false);
-            }
-        }
-
-        public void llLoopSoundMaster(string sound, double volume)
-        {
-            m_host.AddScriptLPS(1);
-            if (m_SoundModule != null)
-            {
-                m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
-                        volume, 20, true);
-            }
-        }
-
-        public void llLoopSoundSlave(string sound, double volume)
-        {
-            m_host.AddScriptLPS(1);
-            lock (m_host.ParentGroup.LoopSoundSlavePrims)
-            {
-                m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host);
-            }
-        }
-
-        public void llPlaySoundSlave(string sound, double volume)
-        {
-            m_host.AddScriptLPS(1);
-
-            // send the sound, once, to all clients in range
-            if (m_SoundModule != null)
-            {
-                m_SoundModule.SendSound(m_host.UUID,
-                        ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
-                        0, true, false);
-            }
-        }
-
-        public void llTriggerSound(string sound, double volume)
-        {
-            m_host.AddScriptLPS(1);
-            // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
-            if (m_SoundModule != null)
-            {
-                m_SoundModule.SendSound(m_host.UUID,
-                        ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0,
-                        false, false);
-            }
-        }
-
-        public void llStopSound()
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_SoundModule != null)
-                m_SoundModule.StopSound(m_host.UUID);
-        }
-
-        public void llPreloadSound(string sound)
-        {
-            m_host.AddScriptLPS(1);
-            if (m_SoundModule != null)
-                m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
-            ScriptSleep(m_sleepMsOnPreloadSound);
-        }
-
-        /// 
-        /// Return a portion of the designated string bounded by
-        /// inclusive indices (start and end). As usual, the negative
-        /// indices, and the tolerance for out-of-bound values, makes
-        /// this more complicated than it might otherwise seem.
-        /// 
-        public LSL_String llGetSubString(string src, int start, int end)
-        {
-            m_host.AddScriptLPS(1);
-
-            // Normalize indices (if negative).
-            // After normlaization they may still be
-            // negative, but that is now relative to
-            // the start, rather than the end, of the
-            // sequence.
-
-            if (start < 0)
-            {
-                start = src.Length+start;
-            }
-            if (end < 0)
-            {
-                end = src.Length+end;
-            }
-
-            // Conventional substring
-            if (start <= end)
-            {
-                // Implies both bounds are out-of-range.
-                if (end < 0 || start >= src.Length)
-                {
-                    return String.Empty;
-                }
-                // If end is positive, then it directly
-                // corresponds to the lengt of the substring
-                // needed (plus one of course). BUT, it
-                // must be within bounds.
-                if (end >= src.Length)
-                {
-                    end = src.Length-1;
-                }
-
-                if (start < 0)
-                {
-                    return src.Substring(0,end+1);
-                }
-                // Both indices are positive
-                return src.Substring(start, (end+1) - start);
-            }
-
-            // Inverted substring (end < start)
-            else
-            {
-                // Implies both indices are below the
-                // lower bound. In the inverted case, that
-                // means the entire string will be returned
-                // unchanged.
-                if (start < 0)
-                {
-                    return src;
-                }
-                // If both indices are greater than the upper
-                // bound the result may seem initially counter
-                // intuitive.
-                if (end >= src.Length)
-                {
-                    return src;
-                }
-
-                if (end < 0)
-                {
-                    if (start < src.Length)
-                    {
-                        return src.Substring(start);
-                    }
-                    else
-                    {
-                        return String.Empty;
-                    }
-                }
-                else
-                {
-                    if (start < src.Length)
-                    {
-                        return src.Substring(0,end+1) + src.Substring(start);
-                    }
-                    else
-                    {
-                        return src.Substring(0,end+1);
-                    }
-                }
-            }
-         }
-
-        /// 
-        /// Delete substring removes the specified substring bounded
-        /// by the inclusive indices start and end. Indices may be
-        /// negative (indicating end-relative) and may be inverted,
-        /// i.e. end < start.
-        /// 
-        public LSL_String llDeleteSubString(string src, int start, int end)
-        {
-            m_host.AddScriptLPS(1);
-
-            // Normalize indices (if negative).
-            // After normlaization they may still be
-            // negative, but that is now relative to
-            // the start, rather than the end, of the
-            // sequence.
-            if (start < 0)
-            {
-                start = src.Length+start;
-            }
-            if (end < 0)
-            {
-                end = src.Length+end;
-            }
-            // Conventionally delimited substring
-            if (start <= end)
-            {
-                // If both bounds are outside of the existing
-                // string, then return unchanges.
-                if (end < 0 || start >= src.Length)
-                {
-                    return src;
-                }
-                // At least one bound is in-range, so we
-                // need to clip the out-of-bound argument.
-                if (start < 0)
-                {
-                    start = 0;
-                }
-
-                if (end >= src.Length)
-                {
-                    end = src.Length-1;
-                }
-
-                return src.Remove(start,end-start+1);
-            }
-            // Inverted substring
-            else
-            {
-                // In this case, out of bounds means that
-                // the existing string is part of the cut.
-                if (start < 0 || end >= src.Length)
-                {
-                    return String.Empty;
-                }
-
-                if (end > 0)
-                {
-                    if (start < src.Length)
-                    {
-                        return src.Remove(start).Remove(0,end+1);
-                    }
-                    else
-                    {
-                        return src.Remove(0,end+1);
-                    }
-                }
-                else
-                {
-                    if (start < src.Length)
-                    {
-                        return src.Remove(start);
-                    }
-                    else
-                    {
-                        return src;
-                    }
-                }
-            }
-        }
-
-        /// 
-        /// Insert string inserts the specified string identified by src
-        /// at the index indicated by index. Index may be negative, in
-        /// which case it is end-relative. The index may exceed either
-        /// string bound, with the result being a concatenation.
-        /// 
-        public LSL_String llInsertString(string dest, int index, string src)
-        {
-            m_host.AddScriptLPS(1);
-
-            // Normalize indices (if negative).
-            // After normlaization they may still be
-            // negative, but that is now relative to
-            // the start, rather than the end, of the
-            // sequence.
-            if (index < 0)
-            {
-                index = dest.Length+index;
-
-                // Negative now means it is less than the lower
-                // bound of the string.
-
-                if (index < 0)
-                {
-                    return src+dest;
-                }
-
-            }
-
-            if (index >= dest.Length)
-            {
-                return dest+src;
-            }
-
-            // The index is in bounds.
-            // In this case the index refers to the index that will
-            // be assigned to the first character of the inserted string.
-            // So unlike the other string operations, we do not add one
-            // to get the correct string length.
-            return dest.Substring(0,index)+src+dest.Substring(index);
-
-        }
-
-        public LSL_String llToUpper(string src)
-        {
-            m_host.AddScriptLPS(1);
-            return src.ToUpper();
-        }
-
-        public LSL_String llToLower(string src)
-        {
-            m_host.AddScriptLPS(1);
-            return src.ToLower();
-        }
-
-        public void llGiveMoney(string destination, int amount)
-        {
-            Util.FireAndForget(x =>
-            {
-                m_host.AddScriptLPS(1);
-
-                if (m_item.PermsGranter == UUID.Zero)
-                    return;
-
-                if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
-                {
-                    Error("llGiveMoney", "No permissions to give money");
-                    return;
-                }
-
-                UUID toID = new UUID();
-
-                if (!UUID.TryParse(destination, out toID))
-                {
-                    Error("llGiveMoney", "Bad key in llGiveMoney");
-                    return;
-                }
-
-                IMoneyModule money = World.RequestModuleInterface();
-
-                if (money == null)
-                {
-                    NotImplemented("llGiveMoney");
-                    return;
-                }
-
-                money.ObjectGiveMoney(
-                    m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
-            }, null, "LSL_Api.llGiveMoney");
-        }
-
-        public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llMakeExplosion", "Use llParticleSystem instead");
-            ScriptSleep(m_sleepMsOnMakeExplosion);
-        }
-
-        public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llMakeFountain", "Use llParticleSystem instead");
-            ScriptSleep(m_sleepMsOnMakeFountain);
-        }
-
-        public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llMakeSmoke", "Use llParticleSystem instead");
-            ScriptSleep(m_sleepMsOnMakeSmoke);
-        }
-
-        public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llMakeFire", "Use llParticleSystem instead");
-            ScriptSleep(m_sleepMsOnMakeFire);
-        }
-
-        public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
-        {
-            m_host.AddScriptLPS(1);
-
-            Util.FireAndForget(x =>
-            {
-                if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
-                    return;
-
-                float dist = (float)llVecDist(llGetPos(), pos);
-
-                if (dist > m_ScriptDistanceFactor * 10.0f)
-                    return;
-
-                TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
-
-                if (item == null)
-                {
-                    Error("llRezAtRoot", "Can't find object '" + inventory + "'");
-                    return;
-                }
-
-                if (item.InvType != (int)InventoryType.Object)
-                {
-                    Error("llRezAtRoot", "Can't create requested object; object is missing from database");
-                    return;
-                }
-
-                // need the magnitude later
-                // float velmag = (float)Util.GetMagnitude(llvel);
-
-                List new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
-
-                // If either of these are null, then there was an unknown error.
-                if (new_groups == null)
-                    return;
-
-                foreach (SceneObjectGroup group in new_groups)
-                {
-                    // objects rezzed with this method are die_at_edge by default.
-                    group.RootPart.SetDieAtEdge(true);
-
-                    group.ResumeScripts();
-
-                    m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
-                            "object_rez", new Object[] {
-                            new LSL_String(
-                            group.RootPart.UUID.ToString()) },
-                            new DetectParams[0]));
-
-                    float groupmass = group.GetMass();
-
-                    PhysicsActor pa = group.RootPart.PhysActor;
-
-                    //Recoil.
-                    if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
-                    {
-                        Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
-                        if (recoil != Vector3.Zero)
-                        {
-                            llApplyImpulse(recoil, 0);
-                        }
-                    }
-                    // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
-                }
-            }, null, "LSL_Api.llRezAtRoot");
-
-            //ScriptSleep((int)((groupmass * velmag) / 10));
-            ScriptSleep(m_sleepMsOnRezAtRoot);
-        }
-
-        public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
-        {
-            llRezAtRoot(inventory, pos, vel, rot, param);
-        }
-
-        public void llLookAt(LSL_Vector target, double strength, double damping)
-        {
-            m_host.AddScriptLPS(1);
-            // Determine where we are looking from
-            LSL_Vector from = llGetPos();
-
-            // normalized direction to target
-            LSL_Vector dir = llVecNorm(target - from);
-            // use vertical to help compute left axis
-            LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
-            // find normalized left axis parallel to horizon
-            LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
-            // make up orthogonal to left and dir
-            up = LSL_Vector.Cross(dir, left);
-
-            // compute rotation based on orthogonal axes
-            LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up);
-
-            // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
-            // set the rotation of the object, copy that behavior
-            PhysicsActor pa = m_host.PhysActor;
-
-            if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical)
-            {
-                llSetRot(rot);
-            }
-            else
-            {
-                m_host.StartLookAt(rot, (float)strength, (float)damping);
-            }
-        }
-
-        public void llStopLookAt()
-        {
-            m_host.AddScriptLPS(1);
-            m_host.StopLookAt();
-        }
-
-        public void llSetTimerEvent(double sec)
-        {
-            if (sec != 0.0 && sec < m_MinTimerInterval)
-                sec = m_MinTimerInterval;
-            m_host.AddScriptLPS(1);
-            // Setting timer repeat
-            AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec);
-        }
-
-        public virtual void llSleep(double sec)
-        {
-//            m_log.Info("llSleep snoozing " + sec + "s.");
-            m_host.AddScriptLPS(1);
-
-            Sleep((int)(sec * 1000));
-        }
-
-        public LSL_Float llGetMass()
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_host.ParentGroup.IsAttachment)
-            {
-                ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
-
-                if (attachedAvatar != null)
-                {
-                    return attachedAvatar.GetMass();
-                }
-                else
-                {
-                    return 0;
-                }
-            }
-            else
-            {
-                if (m_host.IsRoot)
-                {
-                    return m_host.ParentGroup.GetMass();
-                }
-                else
-                {
-                    return m_host.GetMass();
-                }
-            }
-        }
-
-        public LSL_Float llGetMassMKS()
-        {
-            // this is what the wiki says it does!
-            // http://wiki.secondlife.com/wiki/LlGetMassMKS
-            return llGetMass() * 100.0;
-        }
-
-        public void llCollisionFilter(string name, string id, int accept)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.CollisionFilter.Clear();
-            UUID objectID;
-
-            if (!UUID.TryParse(id, out objectID))
-                objectID = UUID.Zero;
-
-            if (objectID == UUID.Zero && name == "")
-                return;
-
-            m_host.CollisionFilter.Add(accept,objectID.ToString() + name);
-        }
-
-        public void llTakeControls(int controls, int accept, int pass_on)
-        {
-            if (m_item.PermsGranter != UUID.Zero)
-            {
-                ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
-
-                if (presence != null)
-                {
-                    if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
-                    {
-                        presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID);
-                    }
-                }
-            }
-
-            m_host.AddScriptLPS(1);
-        }
-
-        public void llReleaseControls()
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_item.PermsGranter != UUID.Zero)
-            {
-                ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
-
-                if (presence != null)
-                {
-                    if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
-                    {
-                        // Unregister controls from Presence
-                        presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
-                        // Remove Take Control permission.
-                        m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
-                    }
-                }
-            }
-        }
-
-        public void llReleaseURL(string url)
-        {
-            m_host.AddScriptLPS(1);
-            if (m_UrlModule != null)
-                m_UrlModule.ReleaseURL(url);
-        }
-
-        /// 
-        /// Attach the object containing this script to the avatar that owns it.
-        /// 
-        /// 
-        /// The attachment point (e.g. ATTACH_CHEST)
-        /// 
-        /// true if the attach suceeded, false if it did not
-        public bool AttachToAvatar(int attachmentPoint)
-        {
-            SceneObjectGroup grp = m_host.ParentGroup;
-            ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
-
-            IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
-
-            if (attachmentsModule != null)
-                return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true);
-            else
-                return false;
-        }
-
-        /// 
-        /// Detach the object containing this script from the avatar it is attached to.
-        /// 
-        /// 
-        /// Nothing happens if the object is not attached.
-        /// 
-        public void DetachFromAvatar()
-        {
-            Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar");
-        }
-
-        private void DetachWrapper(object o)
-        {
-            if (World.AttachmentsModule != null)
-            {
-                SceneObjectPart host = (SceneObjectPart)o;
-                ScenePresence presence = World.GetScenePresence(host.OwnerID);
-                World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup);
-            }
-        }
-
-        public void llAttachToAvatar(int attachmentPoint)
-        {
-            m_host.AddScriptLPS(1);
-
-//            if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
-//                return;
-
-            if (m_item.PermsGranter != m_host.OwnerID)
-                return;
-
-            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
-                AttachToAvatar(attachmentPoint);
-        }
-
-        public void llDetachFromAvatar()
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_host.ParentGroup.AttachmentPoint == 0)
-                return;
-
-            if (m_item.PermsGranter != m_host.OwnerID)
-                return;
-
-            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
-                DetachFromAvatar();
-        }
-
-        public void llTakeCamera(string avatar)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llTakeCamera", "Use llSetCameraParams instead");
-        }
-
-        public void llReleaseCamera(string avatar)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llReleaseCamera", "Use llClearCameraParams instead");
-        }
-
-        public LSL_String llGetOwner()
-        {
-            m_host.AddScriptLPS(1);
-
-            return m_host.OwnerID.ToString();
-        }
-
-        public void llInstantMessage(string user, string message)
-        {
-            m_host.AddScriptLPS(1);
-
-            // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
-            // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
-            // but I don't think we have a list of scenes available from here.
-            // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
-
-            // user is a UUID
-
-            // TODO: figure out values for client, fromSession, and imSessionID
-            // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
-
-            GridInstantMessage msg = new GridInstantMessage();
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.Remoting.Lifetime;
+using System.Text;
+using System.Threading;
+using System.Text.RegularExpressions;
+using Nini.Config;
+using log4net;
+using OpenMetaverse;
+using OpenMetaverse.Assets;
+using OpenMetaverse.Packets;
+using OpenMetaverse.Rendering;
+using OpenSim;
+using OpenSim.Framework;
+
+using OpenSim.Region.CoreModules;
+using OpenSim.Region.CoreModules.World.Land;
+using OpenSim.Region.CoreModules.World.Terrain;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.Framework.Scenes.Animation;
+using OpenSim.Region.Framework.Scenes.Scripting;
+using OpenSim.Region.Physics.Manager;
+using OpenSim.Region.ScriptEngine.Shared;
+using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
+using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
+using OpenSim.Region.ScriptEngine.Interfaces;
+using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
+using OpenSim.Services.Interfaces;
+using GridRegion = OpenSim.Services.Interfaces.GridRegion;
+using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
+using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
+using AssetLandmark = OpenSim.Framework.AssetLandmark;
+using RegionFlags = OpenSim.Framework.RegionFlags;
+
+using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
+using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
+using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
+using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
+using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
+using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
+using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
+using System.Reflection;
+using System.Linq;
+using PermissionMask = OpenSim.Framework.PermissionMask;
+
+namespace OpenSim.Region.ScriptEngine.Shared.Api
+{
+    // MUST be a ref type
+    public class UserInfoCacheEntry
+    {
+        public int time;
+        public UserAccount account;
+        public PresenceInfo pinfo;
+    }
+
+    /// 
+    /// Contains all LSL ll-functions. This class will be in Default AppDomain.
+    /// 
+    public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
+    {
+        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+        public int LlRequestAgentDataCacheTimeoutMs { get; set; }
+
+        protected IScriptEngine m_ScriptEngine;
+        protected SceneObjectPart m_host;
+
+        /// 
+        /// Used for script sleeps when we are using co-operative script termination.
+        /// 
+        /// null if co-operative script termination is not active
+        WaitHandle m_coopSleepHandle;
+
+        /// 
+        /// The timer used by the ScriptInstance to measure how long the script has executed.
+        /// 
+        private Stopwatch m_executionTimer;
+
+        /// 
+        /// The item that hosts this script
+        /// 
+        protected TaskInventoryItem m_item;
+
+        protected bool throwErrorOnNotImplemented = false;
+        protected AsyncCommandManager AsyncCommands = null;
+        protected float m_ScriptDelayFactor = 1.0f;
+        protected float m_ScriptDistanceFactor = 1.0f;
+        protected float m_MinTimerInterval = 0.5f;
+        protected float m_recoilScaleFactor = 0.0f;
+
+        protected DateTime m_timer = DateTime.Now;
+        protected bool m_waitingForScriptAnswer = false;
+        protected bool m_automaticLinkPermission = false;
+        protected IMessageTransferModule m_TransferModule = null;
+        protected int m_notecardLineReadCharsMax = 255;
+        protected int m_scriptConsoleChannel = 0;
+        protected bool m_scriptConsoleChannelEnabled = false;
+        protected IUrlModule m_UrlModule = null;
+        protected Dictionary m_userInfoCache = new Dictionary();
+        protected int EMAIL_PAUSE_TIME = 20;  // documented delay value for smtp.
+        protected int m_sleepMsOnSetTexture = 200;
+        protected int m_sleepMsOnSetLinkTexture = 200;
+        protected int m_sleepMsOnScaleTexture = 200;
+        protected int m_sleepMsOnOffsetTexture = 200;
+        protected int m_sleepMsOnRotateTexture = 200;
+        protected int m_sleepMsOnSetPos = 200;
+        protected int m_sleepMsOnSetRot = 200;
+        protected int m_sleepMsOnSetLocalRot = 200;
+        protected int m_sleepMsOnPreloadSound = 1000;
+        protected int m_sleepMsOnMakeExplosion = 100;
+        protected int m_sleepMsOnMakeFountain = 100;
+        protected int m_sleepMsOnMakeSmoke = 100;
+        protected int m_sleepMsOnMakeFire = 100;
+        protected int m_sleepMsOnRezAtRoot = 100;
+        protected int m_sleepMsOnInstantMessage = 2000;
+        protected int m_sleepMsOnEmail = 20000;
+        protected int m_sleepMsOnCreateLink = 1000;
+        protected int m_sleepMsOnGiveInventory = 3000;
+        protected int m_sleepMsOnRequestAgentData = 100;
+        protected int m_sleepMsOnRequestInventoryData = 1000;
+        protected int m_sleepMsOnSetDamage = 5000;
+        protected int m_sleepMsOnTextBox = 1000;
+        protected int m_sleepMsOnAdjustSoundVolume = 100;
+        protected int m_sleepMsOnEjectFromLand = 5000;
+        protected int m_sleepMsOnAddToLandPassList = 100;
+        protected int m_sleepMsOnDialog = 1000;
+        protected int m_sleepMsOnRemoteLoadScript = 3000;
+        protected int m_sleepMsOnRemoteLoadScriptPin = 3000;
+        protected int m_sleepMsOnOpenRemoteDataChannel = 1000;
+        protected int m_sleepMsOnSendRemoteData = 3000;
+        protected int m_sleepMsOnRemoteDataReply = 3000;
+        protected int m_sleepMsOnCloseRemoteDataChannel = 1000;
+        protected int m_sleepMsOnSetPrimitiveParams = 200;
+        protected int m_sleepMsOnSetLinkPrimitiveParams = 200;
+        protected int m_sleepMsOnXorBase64Strings = 300;
+        protected int m_sleepMsOnSetParcelMusicURL = 2000;
+        protected int m_sleepMsOnGetPrimMediaParams = 1000;
+        protected int m_sleepMsOnGetLinkMedia = 1000;
+        protected int m_sleepMsOnSetPrimMediaParams = 1000;
+        protected int m_sleepMsOnSetLinkMedia = 1000;
+        protected int m_sleepMsOnClearPrimMedia = 1000;
+        protected int m_sleepMsOnClearLinkMedia = 1000;
+        protected int m_sleepMsOnRequestSimulatorData = 1000;
+        protected int m_sleepMsOnLoadURL = 10000;
+        protected int m_sleepMsOnParcelMediaCommandList = 2000;
+        protected int m_sleepMsOnParcelMediaQuery = 2000;
+        protected int m_sleepMsOnModPow = 1000;
+        protected int m_sleepMsOnSetPrimURL = 2000;
+        protected int m_sleepMsOnRefreshPrimURL = 20000;
+        protected int m_sleepMsOnMapDestination = 1000;
+        protected int m_sleepMsOnAddToLandBanList = 100;
+        protected int m_sleepMsOnRemoveFromLandPassList = 100;
+        protected int m_sleepMsOnRemoveFromLandBanList = 100;
+        protected int m_sleepMsOnResetLandBanList = 100;
+        protected int m_sleepMsOnResetLandPassList = 100;
+        protected int m_sleepMsOnGetParcelPrimOwners = 2000;
+        protected int m_sleepMsOnGetNumberOfNotecardLines = 100;
+        protected int m_sleepMsOnGetNotecardLine = 100;
+        protected string m_internalObjectHost = "lsl.opensim.local";
+        protected bool m_restrictEmail = false;
+        protected ISoundModule m_SoundModule = null;
+
+        protected float m_avatarHeightCorrection = 0.2f;
+        protected bool m_useSimpleBoxesInGetBoundingBox = false;
+        protected bool m_addStatsInGetBoundingBox = false;
+
+        //LSL Avatar Bounding Box (lABB), lower (1) and upper (2),
+        //standing (Std), Groundsitting (Grs), Sitting (Sit),
+        //along X, Y and Z axes, constants (0) and coefficients (1)
+        protected float m_lABB1StdX0 = -0.275f;
+        protected float m_lABB2StdX0 = 0.275f;
+        protected float m_lABB1StdY0 = -0.35f;
+        protected float m_lABB2StdY0 = 0.35f;
+        protected float m_lABB1StdZ0 = -0.1f;
+        protected float m_lABB1StdZ1 = -0.5f;
+        protected float m_lABB2StdZ0 = 0.1f;
+        protected float m_lABB2StdZ1 = 0.5f;
+        protected float m_lABB1GrsX0 = -0.3875f;
+        protected float m_lABB2GrsX0 = 0.3875f;
+        protected float m_lABB1GrsY0 = -0.5f;
+        protected float m_lABB2GrsY0 = 0.5f;
+        protected float m_lABB1GrsZ0 = -0.05f;
+        protected float m_lABB1GrsZ1 = -0.375f;
+        protected float m_lABB2GrsZ0 = 0.5f;
+        protected float m_lABB2GrsZ1 = 0.0f;
+        protected float m_lABB1SitX0 = -0.5875f;
+        protected float m_lABB2SitX0 = 0.1875f;
+        protected float m_lABB1SitY0 = -0.35f;
+        protected float m_lABB2SitY0 = 0.35f;
+        protected float m_lABB1SitZ0 = -0.35f;
+        protected float m_lABB1SitZ1 = -0.375f;
+        protected float m_lABB2SitZ0 = -0.25f;
+        protected float m_lABB2SitZ1 = 0.25f;
+
+        protected float m_primSafetyCoeffX = 2.414214f;
+        protected float m_primSafetyCoeffY = 2.414214f;
+        protected float m_primSafetyCoeffZ = 1.618034f;
+        protected bool m_useCastRayV3 = false;
+        protected float m_floatToleranceInCastRay = 0.00001f;
+        protected float m_floatTolerance2InCastRay = 0.001f;
+        protected DetailLevel m_primLodInCastRay = DetailLevel.Medium;
+        protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium;
+        protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest;
+        protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium;
+        protected int m_maxHitsInCastRay = 16;
+        protected int m_maxHitsPerPrimInCastRay = 16;
+        protected int m_maxHitsPerObjectInCastRay = 16;
+        protected bool m_detectExitsInCastRay = false;
+        protected bool m_filterPartsInCastRay = false;
+        protected bool m_doAttachmentsInCastRay = false;
+        protected int m_msThrottleInCastRay = 200;
+        protected int m_msPerRegionInCastRay = 40;
+        protected int m_msPerAvatarInCastRay = 10;
+        protected int m_msMinInCastRay = 2;
+        protected int m_msMaxInCastRay = 40;
+        protected static List m_castRayCalls = new List();
+        protected bool m_useMeshCacheInCastRay = true;
+        protected static Dictionary m_cachedMeshes = new Dictionary();
+
+        //An array of HTTP/1.1 headers that are not allowed to be used
+        //as custom headers by llHTTPRequest.
+        private string[] HttpStandardHeaders =
+        {
+            "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language",
+            "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control",
+            "Connection", "Content-Encoding", "Content-Language",
+            "Content-Length", "Content-Location", "Content-MD5",
+            "Content-Range", "Content-Type", "Date", "ETag", "Expect",
+            "Expires", "From", "Host", "If-Match", "If-Modified-Since",
+            "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified",
+            "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
+            "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
+            "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent",
+            "Vary", "Via", "Warning", "WWW-Authenticate"
+        };
+
+        public void Initialize(
+            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle,
+            Stopwatch executionTimer)
+        {
+            m_ScriptEngine = scriptEngine;
+            m_host = host;
+            m_item = item;
+            m_coopSleepHandle = coopSleepHandle;
+            m_executionTimer = executionTimer;
+
+            LoadConfig();
+
+            m_TransferModule =
+                    m_ScriptEngine.World.RequestModuleInterface();
+            m_UrlModule = m_ScriptEngine.World.RequestModuleInterface();
+            m_SoundModule = m_ScriptEngine.World.RequestModuleInterface();
+
+            AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
+        }
+
+        /// 
+        /// Load configuration items that affect script, object and run-time behavior. */
+        /// 
+        private void LoadConfig()
+        {
+            LlRequestAgentDataCacheTimeoutMs = 20000;
+
+            IConfig seConfig = m_ScriptEngine.Config;
+
+            if (seConfig != null)
+            {
+                m_ScriptDelayFactor =
+                    seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor);
+                m_ScriptDistanceFactor =
+                    seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor);
+                m_MinTimerInterval =
+                    seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval);
+                m_automaticLinkPermission =
+                    seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission);
+                m_notecardLineReadCharsMax =
+                    seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax);
+
+                // Rezzing an object with a velocity can create recoil. This feature seems to have been
+                //    removed from recent versions of SL. The code computes recoil (vel*mass) and scales
+                //    it by this factor. May be zero to turn off recoil all together.
+                m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
+            }
+
+            if (m_notecardLineReadCharsMax > 65535)
+                m_notecardLineReadCharsMax = 65535;
+
+            // load limits for particular subsystems.
+            IConfigSource seConfigSource = m_ScriptEngine.ConfigSource;
+
+            if (seConfigSource != null)
+            {
+                IConfig lslConfig = seConfigSource.Configs["LL-Functions"];
+                if (lslConfig != null)
+                {
+                    m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail);
+                    m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection);
+                    m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox);
+                    m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox);
+                    m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0);
+                    m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0);
+                    m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0);
+                    m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0);
+                    m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0);
+                    m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1);
+                    m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0);
+                    m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1);
+                    m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0);
+                    m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0);
+                    m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0);
+                    m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0);
+                    m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0);
+                    m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1);
+                    m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0);
+                    m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1);
+                    m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0);
+                    m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0);
+                    m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0);
+                    m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0);
+                    m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0);
+                    m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1);
+                    m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0);
+                    m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1);
+                    m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX);
+                    m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY);
+                    m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ);
+                    m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3);
+                    m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay);
+                    m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay);
+                    m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay);
+                    m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay);
+                    m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay);
+                    m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay);
+                    m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay);
+                    m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
+                    m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
+                    m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
+                    m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
+                    m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
+                    m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay);
+                    m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay);
+                    m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay);
+                    m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay);
+                    m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay);
+                    m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay);
+                }
+
+                IConfig smtpConfig = seConfigSource.Configs["SMTP"];
+                if (smtpConfig != null) 
+                {
+                    // there's an smtp config, so load in the snooze time.
+                    EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
+
+                    m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
+                }
+            }
+            m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000;
+        }
+
+        public override Object InitializeLifetimeService()
+        {
+            ILease lease = (ILease)base.InitializeLifetimeService();
+
+            if (lease.CurrentState == LeaseState.Initial)
+            {
+                lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
+//                lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
+//                lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
+            }
+            return lease;
+        }
+
+        protected virtual void ScriptSleep(int delay)
+        {
+            delay = (int)((float)delay * m_ScriptDelayFactor);
+            if (delay == 0)
+                return;
+
+            Sleep(delay);
+        }
+
+        protected virtual void Sleep(int delay)
+        {
+            if (m_executionTimer != null)
+                m_executionTimer.Stop();    // sleep time doesn't count as execution time, since it doesn't use the CPU
+            
+            try
+            {
+                if (m_coopSleepHandle == null)
+                    System.Threading.Thread.Sleep(delay);
+                else
+                    CheckForCoopTermination(delay);
+            }
+            finally
+            {
+                if (m_executionTimer != null)
+                    m_executionTimer.Start();
+            }
+        }
+
+        /// 
+        /// Check for co-operative termination.
+        /// 
+        /// If called with 0, then just the check is performed with no wait.
+        protected virtual void CheckForCoopTermination(int delay)
+        {
+            if (m_coopSleepHandle.WaitOne(delay))
+                throw new ScriptCoopStopException();
+        }
+
+        public Scene World
+        {
+            get { return m_ScriptEngine.World; }
+        }
+
+        public void state(string newState)
+        {
+            m_ScriptEngine.SetState(m_item.ItemID, newState);
+        }
+
+        /// 
+        /// Reset the named script. The script must be present
+        /// in the same prim.
+        /// 
+        public void llResetScript()
+        {
+            m_host.AddScriptLPS(1);
+
+            // We need to tell the URL module, if we hav one, to release
+            // the allocated URLs
+            if (m_UrlModule != null)
+                m_UrlModule.ScriptRemoved(m_item.ItemID);
+
+            m_ScriptEngine.ApiResetScript(m_item.ItemID);
+        }
+
+        public void llResetOtherScript(string name)
+        {
+            UUID item;
+
+            m_host.AddScriptLPS(1);
+
+            if ((item = GetScriptByName(name)) != UUID.Zero)
+                m_ScriptEngine.ResetScript(item);
+            else
+                Error("llResetOtherScript", "Can't find script '" + name + "'");
+        }
+
+        public LSL_Integer llGetScriptState(string name)
+        {
+            UUID item;
+
+            m_host.AddScriptLPS(1);
+
+            if ((item = GetScriptByName(name)) != UUID.Zero)
+            {
+                return m_ScriptEngine.GetScriptState(item) ?1:0;
+            }
+
+            Error("llGetScriptState", "Can't find script '" + name + "'");
+
+            // If we didn't find it, then it's safe to
+            // assume it is not running.
+
+            return 0;
+        }
+
+        public void llSetScriptState(string name, int run)
+        {
+            UUID item;
+
+            m_host.AddScriptLPS(1);
+
+            // These functions are supposed to be robust,
+            // so get the state one step at a time.
+
+            if ((item = GetScriptByName(name)) != UUID.Zero)
+            {
+                m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
+            }
+            else
+            {
+                Error("llSetScriptState", "Can't find script '" + name + "'");
+            }
+        }
+
+        /// 
+        /// Get a given link entity from a linkset (linked objects and any sitting avatars).
+        /// 
+        /// 
+        /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then
+        /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset.
+        /// The ScenePresences receive linknums in the order in which they sat.
+        /// 
+        /// 
+        /// The link entity.  null if not found.
+        /// 
+        /// 
+        /// 
+        /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4).
+        /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned.
+        /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned.  If any
+        /// positive integer is given in this case then null is returned.
+        /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number
+        /// of entities, then the entity which corresponds to that linknum is returned.
+        /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then
+        /// null is returned.
+        /// 
+        public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum)
+        {
+            if (linknum < 0)
+            {
+                if (linknum == ScriptBaseClass.LINK_THIS)
+                    return part;
+                else
+                    return null;
+            }
+
+            int actualPrimCount = part.ParentGroup.PrimCount;
+            List sittingAvatars = part.ParentGroup.GetSittingAvatars();
+            int adjustedPrimCount = actualPrimCount + sittingAvatars.Count;
+
+            // Special case for a single prim.  In this case the linknum is zero.  However, this will not match a single
+            // prim that has any avatars sat upon it (in which case the root prim is link 1).
+            if (linknum == 0)
+            {
+                if (actualPrimCount == 1 && sittingAvatars.Count == 0)
+                    return part;
+
+                return null;
+            }
+            // Special case to handle a single prim with sitting avatars.  GetLinkPart() would only match zero but
+            // here we must match 1 (ScriptBaseClass.LINK_ROOT).
+            else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1)
+            {
+                if (sittingAvatars.Count > 0)
+                    return part.ParentGroup.RootPart;
+                else
+                    return null;
+            }
+            else if (linknum <= adjustedPrimCount)
+            {
+                if (linknum <= actualPrimCount)
+                {
+                    return part.ParentGroup.GetLinkNumPart(linknum);
+                }
+                else
+                {
+                    return sittingAvatars[linknum - actualPrimCount - 1];
+                }
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public List GetLinkParts(int linkType)
+        {
+            return GetLinkParts(m_host, linkType);
+        }
+
+        public static List GetLinkParts(SceneObjectPart part, int linkType)
+        {
+            List ret = new List();
+            ret.Add(part);
+
+            switch (linkType)
+            {
+            case ScriptBaseClass.LINK_SET:
+                return new List(part.ParentGroup.Parts);
+
+            case ScriptBaseClass.LINK_ROOT:
+                ret = new List();
+                ret.Add(part.ParentGroup.RootPart);
+                return ret;
+
+            case ScriptBaseClass.LINK_ALL_OTHERS:
+                ret = new List(part.ParentGroup.Parts);
+
+                if (ret.Contains(part))
+                    ret.Remove(part);
+
+                return ret;
+
+            case ScriptBaseClass.LINK_ALL_CHILDREN:
+                ret = new List(part.ParentGroup.Parts);
+
+                if (ret.Contains(part.ParentGroup.RootPart))
+                    ret.Remove(part.ParentGroup.RootPart);
+                return ret;
+
+            case ScriptBaseClass.LINK_THIS:
+                return ret;
+
+            default:
+                if (linkType < 0)
+                    return new List();
+
+                SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
+                if (target == null)
+                    return new List();
+                ret = new List();
+                ret.Add(target);
+                return ret;
+            }
+        }
+
+        public List GetLinkEntities(int linkType)
+        {
+            return GetLinkEntities(m_host, linkType);
+        }
+
+        public List GetLinkEntities(SceneObjectPart part, int linkType)
+        {
+            List ret;
+
+            switch (linkType)
+            {
+                case ScriptBaseClass.LINK_SET:
+                    return new List(part.ParentGroup.Parts);
+
+                case ScriptBaseClass.LINK_ROOT:
+                    return new List() { part.ParentGroup.RootPart };
+
+                case ScriptBaseClass.LINK_ALL_OTHERS:
+                    ret = new List(part.ParentGroup.Parts);
+
+                    if (ret.Contains(part))
+                        ret.Remove(part);
+
+                    return ret;
+
+                case ScriptBaseClass.LINK_ALL_CHILDREN:
+                    ret = new List(part.ParentGroup.Parts);
+
+                    if (ret.Contains(part.ParentGroup.RootPart))
+                        ret.Remove(part.ParentGroup.RootPart);
+
+                    return ret;
+
+                case ScriptBaseClass.LINK_THIS:
+                    return new List() { part };
+
+                default:
+                    if (linkType < 0)
+                        return new List();
+
+                    ISceneEntity target = GetLinkEntity(part, linkType);
+                    if (target == null)
+                        return new List();
+
+                    return new List() { target };
+            }
+        }
+
+        //These are the implementations of the various ll-functions used by the LSL scripts.
+        public LSL_Float llSin(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (double)Math.Sin(f);
+        }
+
+        public LSL_Float llCos(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (double)Math.Cos(f);
+        }
+
+        public LSL_Float llTan(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (double)Math.Tan(f);
+        }
+
+        public LSL_Float llAtan2(double x, double y)
+        {
+            m_host.AddScriptLPS(1);
+            return (double)Math.Atan2(x, y);
+        }
+
+        public LSL_Float llSqrt(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (double)Math.Sqrt(f);
+        }
+
+        public LSL_Float llPow(double fbase, double fexponent)
+        {
+            m_host.AddScriptLPS(1);
+            return (double)Math.Pow(fbase, fexponent);
+        }
+
+        public LSL_Integer llAbs(int i)
+        {
+            // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
+            m_host.AddScriptLPS(1);
+            if (i == Int32.MinValue)
+                return i;
+            else
+                return (int)Math.Abs(i);
+        }
+
+        public LSL_Float llFabs(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (double)Math.Abs(f);
+        }
+
+        public LSL_Float llFrand(double mag)
+        {
+            m_host.AddScriptLPS(1);
+
+            return Util.RandomClass.NextDouble() * mag;
+        }
+
+        public LSL_Integer llFloor(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (int)Math.Floor(f);
+        }
+
+        public LSL_Integer llCeil(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (int)Math.Ceiling(f);
+        }
+
+        // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
+        public LSL_Integer llRound(double f)
+        {
+            m_host.AddScriptLPS(1);
+            return (int)Math.Round(f, MidpointRounding.AwayFromZero);
+        }
+
+        //This next group are vector operations involving squaring and square root. ckrinke
+        public LSL_Float llVecMag(LSL_Vector v)
+        {
+            m_host.AddScriptLPS(1);
+            return LSL_Vector.Mag(v);
+        }
+
+        public LSL_Vector llVecNorm(LSL_Vector v)
+        {
+            m_host.AddScriptLPS(1);
+            return LSL_Vector.Norm(v);
+        }
+
+        private double VecDist(LSL_Vector a, LSL_Vector b)
+        {
+            double dx = a.x - b.x;
+            double dy = a.y - b.y;
+            double dz = a.z - b.z;
+            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
+        }
+
+        public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
+        {
+            m_host.AddScriptLPS(1);
+            return VecDist(a, b);
+        }
+
+        //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
+
+        /// 
+        /// Convert an LSL rotation to a Euler vector.
+        /// 
+        /// 
+        /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
+        /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
+        /// 
+        /// 
+        /// 
+        public LSL_Vector llRot2Euler(LSL_Rotation r)
+        {
+            m_host.AddScriptLPS(1);
+
+            LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r;   // Z axis unit vector unaffected by Z rotation component of r.
+            double m = LSL_Vector.Mag(v);                       // Just in case v isn't normalized, need magnitude for Asin() operation later.
+            if (m == 0.0) return new LSL_Vector();
+            double x = Math.Atan2(-v.y, v.z);
+            double sin = v.x / m;
+            if (sin < -0.999999 || sin > 0.999999) x = 0.0;     // Force X rotation to 0 at the singularities.
+            double y = Math.Asin(sin);
+            // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
+            v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0)));
+            double z = Math.Atan2(v.y, v.x);
+
+            return new LSL_Vector(x, y, z);
+        }
+
+        /* From wiki:
+        The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
+        in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
+        a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
+        vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
+        */
+
+        /* How we arrived at this llEuler2Rot
+         *
+         * Experiment in SL to determine conventions:
+         *   llEuler2Rot()=<1,0,0,0>
+         *   llEuler2Rot(<0,PI,0>)=<0,1,0,0>
+         *   llEuler2Rot(<0,0,PI>)=<0,0,1,0>
+         *
+         * Important facts about Quaternions
+         *  - multiplication is non-commutative (a*b != b*a)
+         *  - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
+         *
+         * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
+         *   Qx = c1+i*s1
+         *   Qy = c2+j*s2;
+         *   Qz = c3+k*s3;
+         *
+         * Rotations applied in order (from above) Z, Y, X
+         * Q = (Qz * Qy) * Qx
+         * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
+         * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
+         * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
+         * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
+         * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3   -s1*s2*s3
+         * regroup: x=i*(s1*c2*c3+c1*s2*s3)
+         *          y=j*(c1*s2*c3-s1*c2*s3)
+         *          z=k*(s1*s2*c3+c1*c2*s3)
+         *          s=   c1*c2*c3-s1*s2*s3
+         *
+         * This implementation agrees with the functions found here:
+         * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
+         * And with the results in SL.
+         *
+         * It's also possible to calculate llEuler2Rot by direct multiplication of
+         * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
+         * from the wiki).
+         * Apparently in some cases this is better from a numerical precision perspective?
+         */
+
+        public LSL_Rotation llEuler2Rot(LSL_Vector v)
+        {
+            m_host.AddScriptLPS(1);
+
+            double x,y,z,s;
+
+            double c1 = Math.Cos(v.x * 0.5);
+            double c2 = Math.Cos(v.y * 0.5);
+            double c3 = Math.Cos(v.z * 0.5);
+            double s1 = Math.Sin(v.x * 0.5);
+            double s2 = Math.Sin(v.y * 0.5);
+            double s3 = Math.Sin(v.z * 0.5);
+
+            x = s1 * c2 * c3 + c1 * s2 * s3;
+            y = c1 * s2 * c3 - s1 * c2 * s3;
+            z = s1 * s2 * c3 + c1 * c2 * s3;
+            s = c1 * c2 * c3 - s1 * s2 * s3;
+
+            return new LSL_Rotation(x, y, z, s);
+        }
+
+        public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
+        {
+            m_host.AddScriptLPS(1);
+            double s;
+            double tr = fwd.x + left.y + up.z + 1.0;
+
+            if (tr >= 1.0)
+            {
+                s = 0.5 / Math.Sqrt(tr);
+                return new LSL_Rotation(
+                        (left.z - up.y) * s,
+                        (up.x - fwd.z) * s,
+                        (fwd.y - left.x) * s,
+                        0.25 / s);
+            }
+            else
+            {
+                double max = (left.y > up.z) ? left.y : up.z;
+
+                if (max < fwd.x)
+                {
+                    s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
+                    double x = s * 0.5;
+                    s = 0.5 / s;
+                    return new LSL_Rotation(
+                            x,
+                            (fwd.y + left.x) * s,
+                            (up.x + fwd.z) * s,
+                            (left.z - up.y) * s);
+                }
+                else if (max == left.y)
+                {
+                    s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
+                    double y = s * 0.5;
+                    s = 0.5 / s;
+                    return new LSL_Rotation(
+                            (fwd.y + left.x) * s,
+                            y,
+                            (left.z + up.y) * s,
+                            (up.x - fwd.z) * s);
+                }
+                else
+                {
+                    s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
+                    double z = s * 0.5;
+                    s = 0.5 / s;
+                    return new LSL_Rotation(
+                            (up.x + fwd.z) * s,
+                            (left.z + up.y) * s,
+                            z,
+                            (fwd.y - left.x) * s);
+                }
+            }
+        }
+
+        public LSL_Vector llRot2Fwd(LSL_Rotation r)
+        {
+            m_host.AddScriptLPS(1);
+
+            double x, y, z, m;
+
+            m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
+            // m is always greater than zero
+            // if m is not equal to 1 then Rotation needs to be normalized
+            if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
+            {
+                m = 1.0 / Math.Sqrt(m);
+                r.x *= m;
+                r.y *= m;
+                r.z *= m;
+                r.s *= m;
+            }
+
+            // Fast Algebric Calculations instead of Vectors & Quaternions Product
+            x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
+            y = 2 * (r.x * r.y + r.z * r.s);
+            z = 2 * (r.x * r.z - r.y * r.s);
+            return (new LSL_Vector(x, y, z));
+        }
+
+        public LSL_Vector llRot2Left(LSL_Rotation r)
+        {
+            m_host.AddScriptLPS(1);
+
+            double x, y, z, m;
+
+            m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
+            // m is always greater than zero
+            // if m is not equal to 1 then Rotation needs to be normalized
+            if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
+            {
+                m = 1.0 / Math.Sqrt(m);
+                r.x *= m;
+                r.y *= m;
+                r.z *= m;
+                r.s *= m;
+            }
+
+            // Fast Algebric Calculations instead of Vectors & Quaternions Product
+            x = 2 * (r.x * r.y - r.z * r.s);
+            y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
+            z = 2 * (r.x * r.s + r.y * r.z);
+            return (new LSL_Vector(x, y, z));
+        }
+
+        public LSL_Vector llRot2Up(LSL_Rotation r)
+        {
+            m_host.AddScriptLPS(1);
+            double x, y, z, m;
+
+            m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
+            // m is always greater than zero
+            // if m is not equal to 1 then Rotation needs to be normalized
+            if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
+            {
+                m = 1.0 / Math.Sqrt(m);
+                r.x *= m;
+                r.y *= m;
+                r.z *= m;
+                r.s *= m;
+            }
+
+            // Fast Algebric Calculations instead of Vectors & Quaternions Product
+            x = 2 * (r.x * r.z + r.y * r.s);
+            y = 2 * (-r.x * r.s + r.y * r.z);
+            z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
+            return (new LSL_Vector(x, y, z));
+        }
+
+        public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
+        {
+            //A and B should both be normalized
+            m_host.AddScriptLPS(1);
+            LSL_Rotation rotBetween;
+            // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
+            // continue calculation.
+            if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
+            {
+                rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
+            }
+            else
+            {
+                a = LSL_Vector.Norm(a);
+                b = LSL_Vector.Norm(b);
+                double dotProduct = LSL_Vector.Dot(a, b);
+                // There are two degenerate cases possible. These are for vectors 180 or
+                // 0 degrees apart. These have to be detected and handled individually.
+                //
+                // Check for vectors 180 degrees apart.
+                // A dot product of -1 would mean the angle between vectors is 180 degrees.
+                if (dotProduct < -0.9999999f)
+                {
+                    // First assume X axis is orthogonal to the vectors.
+                    LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
+                    orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
+                    // Check for near zero vector. A very small non-zero number here will create
+                    // a rotation in an undesired direction.
+                    if (LSL_Vector.Mag(orthoVector) > 0.0001)
+                    {
+                        rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f);
+                    }
+                    // If the magnitude of the vector was near zero, then assume the X axis is not
+                    // orthogonal and use the Z axis instead.
+                    else
+                    {
+                        // Set 180 z rotation.
+                        rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
+                    }
+                }
+                // Check for parallel vectors.
+                // A dot product of 1 would mean the angle between vectors is 0 degrees.
+                else if (dotProduct > 0.9999999f)
+                {
+                    // Set zero rotation.
+                    rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
+                }
+                else
+                {
+                    // All special checks have been performed so get the axis of rotation.
+                    LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
+                    // Quarternion s value is the length of the unit vector + dot product.
+                    double qs = 1.0 + dotProduct;
+                    rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
+                    // Normalize the rotation.
+                    double mag = LSL_Rotation.Mag(rotBetween);
+                    // We shouldn't have to worry about a divide by zero here. The qs value will be
+                    // non-zero because we already know if we're here, then the dotProduct is not -1 so
+                    // qs will not be zero. Also, we've already handled the input vectors being zero so the
+                    // crossProduct vector should also not be zero.
+                    rotBetween.x = rotBetween.x / mag;
+                    rotBetween.y = rotBetween.y / mag;
+                    rotBetween.z = rotBetween.z / mag;
+                    rotBetween.s = rotBetween.s / mag;
+                    // Check for undefined values and set zero rotation if any found. This code might not actually be required
+                    // any longer since zero vectors are checked for at the top.
+                    if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
+                    {
+                        rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
+                    }
+                }
+            }
+            return rotBetween;
+        }
+
+        public void llWhisper(int channelID, string text)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (text.Length > 1023)
+                text = text.Substring(0, 1023);
+
+            World.SimChat(Utils.StringToBytes(text),
+                          ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
+
+            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+            if (wComm != null)
+                wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
+        }
+
+        public void llSay(int channelID, string text)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
+            {
+                Console.WriteLine(text);
+            }
+            else
+            {
+                if (text.Length > 1023)
+                    text = text.Substring(0, 1023);
+
+                World.SimChat(Utils.StringToBytes(text),
+                              ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
+
+                IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+                if (wComm != null)
+                    wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
+            }
+        }
+
+        public void llShout(int channelID, string text)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (text.Length > 1023)
+                text = text.Substring(0, 1023);
+
+            World.SimChat(Utils.StringToBytes(text),
+                          ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
+
+            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+            if (wComm != null)
+                wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
+        }
+
+        public void llRegionSay(int channelID, string text)
+        {
+            if (channelID == 0)
+            {
+                Error("llRegionSay", "Cannot use on channel 0");
+                return;
+            }
+
+            if (text.Length > 1023)
+                text = text.Substring(0, 1023);
+
+            m_host.AddScriptLPS(1);
+
+            World.SimChat(Utils.StringToBytes(text),
+                          ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
+
+            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+            if (wComm != null)
+                wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
+        }
+
+        public void  llRegionSayTo(string target, int channel, string msg)
+        {
+            if (msg.Length > 1023)
+                msg = msg.Substring(0, 1023);
+
+            m_host.AddScriptLPS(1);
+
+            if (channel == ScriptBaseClass.DEBUG_CHANNEL)
+            {
+                return;
+            }
+
+            UUID TargetID;
+            UUID.TryParse(target, out TargetID);
+
+            World.SimChatToAgent(TargetID, Utils.StringToBytes(msg),
+                          channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
+
+            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+            if (wComm != null)
+                wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
+        }
+
+        public LSL_Integer llListen(int channelID, string name, string ID, string msg)
+        {
+            m_host.AddScriptLPS(1);
+            UUID keyID;
+            UUID.TryParse(ID, out keyID);
+            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+            if (wComm != null)
+                return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg);
+            else
+                return -1;
+        }
+
+        public void llListenControl(int number, int active)
+        {
+            m_host.AddScriptLPS(1);
+            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+            if (wComm != null)
+                wComm.ListenControl(m_item.ItemID, number, active);
+        }
+
+        public void llListenRemove(int number)
+        {
+            m_host.AddScriptLPS(1);
+            IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
+            if (wComm != null)
+                wComm.ListenRemove(m_item.ItemID, number);
+        }
+
+        public void llSensor(string name, string id, int type, double range, double arc)
+        {
+            m_host.AddScriptLPS(1);
+            UUID keyID = UUID.Zero;
+            UUID.TryParse(id, out keyID);
+
+            AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host);
+       }
+
+        public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
+        {
+            m_host.AddScriptLPS(1);
+            UUID keyID = UUID.Zero;
+            UUID.TryParse(id, out keyID);
+
+            AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host);
+        }
+
+        public void llSensorRemove()
+        {
+            m_host.AddScriptLPS(1);
+            AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID);
+        }
+
+        public string resolveName(UUID objecUUID)
+        {
+            // try avatar username surname
+            UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID);
+            if (account != null)
+            {
+                string avatarname = account.Name;
+                return avatarname;
+            }
+            // try an scene object
+            SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
+            if (SOP != null)
+            {
+                string objectname = SOP.Name;
+                return objectname;
+            }
+
+            EntityBase SensedObject;
+            World.Entities.TryGetValue(objecUUID, out SensedObject);
+
+            if (SensedObject == null)
+            {
+                IGroupsModule groups = World.RequestModuleInterface();
+                if (groups != null)
+                {
+                    GroupRecord gr = groups.GetGroupRecord(objecUUID);
+                    if (gr != null)
+                        return gr.GroupName;
+                }
+                return String.Empty;
+            }
+
+            return SensedObject.Name;
+        }
+
+        public LSL_String llDetectedName(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return String.Empty;
+            return detectedParams.Name;
+        }
+
+        public LSL_String llDetectedKey(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return String.Empty;
+            return detectedParams.Key.ToString();
+        }
+
+        public LSL_String llDetectedOwner(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return String.Empty;
+            return detectedParams.Owner.ToString();
+        }
+
+        public LSL_Integer llDetectedType(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return 0;
+            return new LSL_Integer(detectedParams.Type);
+        }
+
+        public LSL_Vector llDetectedPos(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return new LSL_Vector();
+            return detectedParams.Position;
+        }
+
+        public LSL_Vector llDetectedVel(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return new LSL_Vector();
+            return detectedParams.Velocity;
+        }
+
+        public LSL_Vector llDetectedGrab(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (parms == null)
+                return new LSL_Vector(0, 0, 0);
+
+            return parms.OffsetPos;
+        }
+
+        public LSL_Rotation llDetectedRot(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return new LSL_Rotation();
+            return detectedParams.Rotation;
+        }
+
+        public LSL_Integer llDetectedGroup(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (detectedParams == null)
+                return new LSL_Integer(0);
+            if (m_host.GroupID == detectedParams.Group)
+                return new LSL_Integer(1);
+            return new LSL_Integer(0);
+        }
+
+        public LSL_Integer llDetectedLinkNumber(int number)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+            if (parms == null)
+                return new LSL_Integer(0);
+
+            return new LSL_Integer(parms.LinkNum);
+        }
+
+        /// 
+        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
+        /// 
+        public LSL_Vector llDetectedTouchBinormal(int index)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
+            if (detectedParams == null)
+                return new LSL_Vector();
+            return detectedParams.TouchBinormal;
+        }
+
+        /// 
+        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
+        /// 
+        public LSL_Integer llDetectedTouchFace(int index)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
+            if (detectedParams == null)
+                return new LSL_Integer(-1);
+            return new LSL_Integer(detectedParams.TouchFace);
+        }
+
+        /// 
+        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
+        /// 
+        public LSL_Vector llDetectedTouchNormal(int index)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
+            if (detectedParams == null)
+                return new LSL_Vector();
+            return detectedParams.TouchNormal;
+        }
+
+        /// 
+        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
+        /// 
+        public LSL_Vector llDetectedTouchPos(int index)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
+            if (detectedParams == null)
+                return new LSL_Vector();
+            return detectedParams.TouchPos;
+        }
+
+        /// 
+        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
+        /// 
+        public LSL_Vector llDetectedTouchST(int index)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
+            if (detectedParams == null)
+                return new LSL_Vector(-1.0, -1.0, 0.0);
+            return detectedParams.TouchST;
+        }
+
+        /// 
+        /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
+        /// 
+        public LSL_Vector llDetectedTouchUV(int index)
+        {
+            m_host.AddScriptLPS(1);
+            DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
+            if (detectedParams == null)
+                return new LSL_Vector(-1.0, -1.0, 0.0);
+            return detectedParams.TouchUV;
+        }
+
+        public virtual void llDie()
+        {
+            m_host.AddScriptLPS(1);
+            throw new SelfDeleteException();
+        }
+
+        public LSL_Float llGround(LSL_Vector offset)
+        {
+            m_host.AddScriptLPS(1);
+            Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
+
+            //Get the slope normal.  This gives us the equation of the plane tangent to the slope.
+            LSL_Vector vsn = llGroundNormal(offset);
+
+            // Clamp to valid position
+            if (pos.X < 0)
+                pos.X = 0;
+            else if (pos.X >= World.Heightmap.Width)
+                pos.X = World.Heightmap.Width - 1;
+            if (pos.Y < 0)
+                pos.Y = 0;
+            else if (pos.Y >= World.Heightmap.Height)
+                pos.Y = World.Heightmap.Height - 1;
+
+            //Get the height for the integer coordinates from the Heightmap
+            float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y];
+
+            //Calculate the difference between the actual coordinates and the integer coordinates
+            float xdiff = pos.X - (float)((int)pos.X);
+            float ydiff = pos.Y - (float)((int)pos.Y);
+
+            //Use the equation of the tangent plane to adjust the height to account for slope
+
+            return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight;
+        }
+
+        public LSL_Float llCloud(LSL_Vector offset)
+        {
+            m_host.AddScriptLPS(1);
+            float cloudCover = 0f;
+            ICloudModule module = World.RequestModuleInterface();
+            if (module != null)
+            {
+                Vector3 pos = m_host.GetWorldPosition();
+                int x = (int)(pos.X + offset.x);
+                int y = (int)(pos.Y + offset.y);
+
+                cloudCover = module.CloudCover(x, y, 0);
+
+            }
+            return cloudCover;
+        }
+
+        public LSL_Vector llWind(LSL_Vector offset)
+        {
+            m_host.AddScriptLPS(1);
+            LSL_Vector wind = new LSL_Vector(0, 0, 0);
+            IWindModule module = World.RequestModuleInterface();
+            if (module != null)
+            {
+                Vector3 pos = m_host.GetWorldPosition();
+                int x = (int)(pos.X + offset.x);
+                int y = (int)(pos.Y + offset.y);
+
+                Vector3 windSpeed = module.WindSpeed(x, y, 0);
+
+                wind.x = windSpeed.X;
+                wind.y = windSpeed.Y;
+            }
+            return wind;
+        }
+
+        public void llSetStatus(int status, int value)
+        {
+            m_host.AddScriptLPS(1);
+
+            int statusrotationaxis = 0;
+
+            if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
+            {
+                if (value != 0)
+                {
+                    SceneObjectGroup group = m_host.ParentGroup;
+                    bool allow = true;
+
+                    foreach (SceneObjectPart part in group.Parts)
+                    {
+                        if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
+                        {
+                            allow = false;
+                            break;
+                        }
+                    }
+
+                    if (!allow)
+                        return;
+
+                    m_host.ScriptSetPhysicsStatus(true);
+                }
+                else
+                {
+                    m_host.ScriptSetPhysicsStatus(false);
+                }
+            }
+
+            if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
+            {
+                m_host.ParentGroup.ScriptSetPhantomStatus(value != 0);
+            }
+
+            if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
+            {
+                m_host.AddFlag(PrimFlags.CastShadows);
+            }
+
+            if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
+            {
+                statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
+            }
+
+            if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
+            {
+                statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
+            }
+
+            if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
+            {
+                statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
+            }
+
+            if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
+                m_host.BlockGrab = value != 0;
+
+            if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
+                m_host.ParentGroup.BlockGrabOverride = value != 0;
+
+            if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
+            {
+                if (value != 0)
+                    m_host.SetDieAtEdge(true);
+                else
+                    m_host.SetDieAtEdge(false);
+            }
+
+            if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
+            {
+                if (value != 0)
+                    m_host.SetReturnAtEdge(true);
+                else
+                    m_host.SetReturnAtEdge(false);
+            }
+
+            if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
+            {
+                if (value != 0)
+                    m_host.SetStatusSandbox(true);
+                else
+                    m_host.SetStatusSandbox(false);
+            }
+
+            if (statusrotationaxis != 0)
+            {
+                m_host.SetAxisRotation(statusrotationaxis, value);
+            }
+        }
+
+        private bool IsPhysical()
+        {
+            return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics);
+        }
+
+        public LSL_Integer llGetStatus(int status)
+        {
+            m_host.AddScriptLPS(1);
+            // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
+            switch (status)
+            {
+                case ScriptBaseClass.STATUS_PHYSICS:
+                    return IsPhysical() ? 1 : 0;
+
+                case ScriptBaseClass.STATUS_PHANTOM:
+                    if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
+                    {
+                        return 1;
+                    }
+                    return 0;
+
+                case ScriptBaseClass.STATUS_CAST_SHADOWS:
+                    if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
+                    {
+                        return 1;
+                    }
+                    return 0;
+
+                case ScriptBaseClass.STATUS_BLOCK_GRAB:
+                    return m_host.BlockGrab ? 1 : 0;
+
+                case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT:
+                    return m_host.ParentGroup.BlockGrabOverride ? 1 : 0;
+
+                case ScriptBaseClass.STATUS_DIE_AT_EDGE:
+                    if (m_host.GetDieAtEdge())
+                        return 1;
+                    else
+                        return 0;
+
+                case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
+                    if (m_host.GetReturnAtEdge())
+                        return 1;
+                    else
+                        return 0;
+
+                case ScriptBaseClass.STATUS_ROTATE_X:
+                    // if (m_host.GetAxisRotation(2) != 0)
+                    if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
+                        return 1;
+                    else
+                        return 0;
+
+                case ScriptBaseClass.STATUS_ROTATE_Y:
+                    if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
+                        return 1;
+                    else
+                        return 0;
+
+                case ScriptBaseClass.STATUS_ROTATE_Z:
+                    if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
+                        return 1;
+                    else
+                        return 0;
+
+                case ScriptBaseClass.STATUS_SANDBOX:
+                    if (m_host.GetStatusSandbox())
+                        return 1;
+                    else
+                        return 0;
+            }
+            return 0;
+        }
+
+        public void llSetScale(LSL_Vector scale)
+        {
+            m_host.AddScriptLPS(1);
+            SetScale(m_host, scale);
+        }
+
+        protected void SetScale(SceneObjectPart part, LSL_Vector scale)
+        {
+            // TODO: this needs to trigger a persistance save as well
+            if (part == null || part.ParentGroup.IsDeleted)
+                return;
+
+            // First we need to check whether or not we need to clamp the size of a physics-enabled prim
+            PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
+            if (pa != null && pa.IsPhysical)
+            {
+                scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
+                scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
+                scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
+            }
+            else
+            {
+                // If not physical, then we clamp the scale to the non-physical min/max
+                scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
+                scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
+                scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
+            }
+
+            Vector3 tmp = part.Scale;
+            tmp.X = (float)scale.x;
+            tmp.Y = (float)scale.y;
+            tmp.Z = (float)scale.z;
+            part.Scale = tmp;
+            part.SendFullUpdateToAllClients();
+        }
+
+        public LSL_Vector llGetScale()
+        {
+            m_host.AddScriptLPS(1);
+            return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
+        }
+
+        public void llSetClickAction(int action)
+        {
+            m_host.AddScriptLPS(1);
+            m_host.ClickAction = (byte)action;
+            m_host.ParentGroup.HasGroupChanged = true;
+            m_host.ScheduleFullUpdate();
+            return;
+        }
+
+        public void llSetColor(LSL_Vector color, int face)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (face == ScriptBaseClass.ALL_SIDES)
+                face = SceneObjectPart.ALL_SIDES;
+
+            m_host.SetFaceColorAlpha(face, color, null);
+        }
+
+        public void llSetContentType(LSL_Key id, LSL_Integer type)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (m_UrlModule == null)
+                return;
+
+            // Make sure the content type is text/plain to start with
+            m_UrlModule.HttpContentType(new UUID(id), "text/plain");
+
+            // Is the object owner online and in the region
+            ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID);
+            if (agent == null || agent.IsChildAgent)
+                return;  // Fail if the owner is not in the same region
+
+            // Is it the embeded browser?
+            string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
+            if (userAgent.IndexOf("SecondLife") < 0)
+                return; // Not the embedded browser. Is this check good enough?
+
+            // Use the IP address of the client and check against the request
+            // seperate logins from the same IP will allow all of them to get non-text/plain as long
+            // as the owner is in the region. Same as SL!
+            string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString();
+            string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr");
+            //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'");
+            if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "")
+                return;
+            if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "")
+                return;
+
+            // If the request isnt from the same IP address then the request cannot be from the owner
+            if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim()))
+                return;
+
+            switch (type)
+            {
+                case ScriptBaseClass.CONTENT_TYPE_HTML:
+                    m_UrlModule.HttpContentType(new UUID(id), "text/html");
+                    break;
+                case ScriptBaseClass.CONTENT_TYPE_XML:
+                    m_UrlModule.HttpContentType(new UUID(id), "application/xml");
+                    break;
+                case ScriptBaseClass.CONTENT_TYPE_XHTML:
+                    m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml");
+                    break;
+                case ScriptBaseClass.CONTENT_TYPE_ATOM:
+                    m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml");
+                    break;
+                case ScriptBaseClass.CONTENT_TYPE_JSON:
+                    m_UrlModule.HttpContentType(new UUID(id), "application/json");
+                    break;
+                case ScriptBaseClass.CONTENT_TYPE_LLSD:
+                    m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml");
+                    break;
+                case ScriptBaseClass.CONTENT_TYPE_FORM:
+                    m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded");
+                    break;
+                case ScriptBaseClass.CONTENT_TYPE_RSS:
+                    m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml");
+                    break;
+                default:
+                    m_UrlModule.HttpContentType(new UUID(id), "text/plain");
+                    break;
+            }
+        }
+
+        public void SetTexGen(SceneObjectPart part, int face,int style)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            MappingType textype;
+            textype = MappingType.Default;
+            if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
+                textype = MappingType.Planar;
+
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                tex.CreateFace((uint) face);
+                tex.FaceTextures[face].TexMapType = textype;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            else if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (uint i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        tex.FaceTextures[i].TexMapType = textype;
+                    }
+                    tex.DefaultTexture.TexMapType = textype;
+                }
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        public void SetGlow(SceneObjectPart part, int face, float glow)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                tex.CreateFace((uint) face);
+                tex.FaceTextures[face].Glow = glow;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            else if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (uint i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        tex.FaceTextures[i].Glow = glow;
+                    }
+                    tex.DefaultTexture.Glow = glow;
+                }
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
+        {
+
+            Shininess sval = new Shininess();
+
+            switch (shiny)
+            {
+            case 0:
+                sval = Shininess.None;
+                break;
+            case 1:
+                sval = Shininess.Low;
+                break;
+            case 2:
+                sval = Shininess.Medium;
+                break;
+            case 3:
+                sval = Shininess.High;
+                break;
+            default:
+                sval = Shininess.None;
+                break;
+            }
+
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                tex.CreateFace((uint) face);
+                tex.FaceTextures[face].Shiny = sval;
+                tex.FaceTextures[face].Bump = bump;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            else if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (uint i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        tex.FaceTextures[i].Shiny = sval;
+                        tex.FaceTextures[i].Bump = bump;
+                    }
+                    tex.DefaultTexture.Shiny = sval;
+                    tex.DefaultTexture.Bump = bump;
+                }
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        public void SetFullBright(SceneObjectPart part, int face, bool bright)
+        {
+             Primitive.TextureEntry tex = part.Shape.Textures;
+             if (face >= 0 && face < GetNumberOfSides(part))
+             {
+                 tex.CreateFace((uint) face);
+                 tex.FaceTextures[face].Fullbright = bright;
+                 part.UpdateTextureEntry(tex.GetBytes());
+                 return;
+             }
+             else if (face == ScriptBaseClass.ALL_SIDES)
+             {
+                 for (uint i = 0; i < GetNumberOfSides(part); i++)
+                 {
+                     if (tex.FaceTextures[i] != null)
+                     {
+                         tex.FaceTextures[i].Fullbright = bright;
+                     }
+                 }
+                 tex.DefaultTexture.Fullbright = bright;
+                 part.UpdateTextureEntry(tex.GetBytes());
+                 return;
+             }
+         }
+
+        public LSL_Float llGetAlpha(int face)
+        {
+            m_host.AddScriptLPS(1);
+
+            return GetAlpha(m_host, face);
+        }
+
+        protected LSL_Float GetAlpha(SceneObjectPart part, int face)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                int i;
+                double sum = 0.0;
+                for (i = 0 ; i < GetNumberOfSides(part); i++)
+                    sum += (double)tex.GetFace((uint)i).RGBA.A;
+                return sum;
+            }
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                return (double)tex.GetFace((uint)face).RGBA.A;
+            }
+            return 0.0;
+        }
+
+        public void llSetAlpha(double alpha, int face)
+        {
+            m_host.AddScriptLPS(1);
+
+            SetAlpha(m_host, alpha, face);
+        }
+
+        public void llSetLinkAlpha(int linknumber, double alpha, int face)
+        {
+            m_host.AddScriptLPS(1);
+
+            List parts = GetLinkParts(linknumber);
+
+            foreach (SceneObjectPart part in parts)
+                SetAlpha(part, alpha, face);
+        }
+
+        protected void SetAlpha(SceneObjectPart part, double alpha, int face)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            Color4 texcolor;
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                texcolor = tex.CreateFace((uint)face).RGBA;
+                texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
+                tex.FaceTextures[face].RGBA = texcolor;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            else if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (int i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        texcolor = tex.FaceTextures[i].RGBA;
+                        texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
+                        tex.FaceTextures[i].RGBA = texcolor;
+                    }
+                }
+
+                // In some cases, the default texture can be null, eg when every face
+                // has a unique texture
+                if (tex.DefaultTexture != null)
+                {
+                    texcolor = tex.DefaultTexture.RGBA;
+                    texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
+                    tex.DefaultTexture.RGBA = texcolor;
+                }
+
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        /// 
+        /// Set flexi parameters of a part.
+        ///
+        /// FIXME: Much of this code should probably be within the part itself.
+        /// 
+        /// 
+        /// 
+        /// 
+        /// 
+        /// 
+        /// 
+        /// 
+        /// 
+        protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
+            float wind, float tension, LSL_Vector Force)
+        {
+            if (part == null)
+                return;
+
+            if (flexi)
+            {
+                part.Shape.FlexiEntry = true;   // this setting flexi true isn't working, but the below parameters do
+                                                                // work once the prim is already flexi
+                part.Shape.FlexiSoftness = softness;
+                part.Shape.FlexiGravity = gravity;
+                part.Shape.FlexiDrag = friction;
+                part.Shape.FlexiWind = wind;
+                part.Shape.FlexiTension = tension;
+                part.Shape.FlexiForceX = (float)Force.x;
+                part.Shape.FlexiForceY = (float)Force.y;
+                part.Shape.FlexiForceZ = (float)Force.z;
+                part.Shape.PathCurve = (byte)Extrusion.Flexible;
+            }
+            else
+            {
+                // Other values not set, they do not seem to be sent to the viewer
+                // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off
+                part.Shape.PathCurve = (byte)Extrusion.Straight;
+                part.Shape.FlexiEntry = false;
+            }
+            part.ParentGroup.HasGroupChanged = true;
+            part.ScheduleFullUpdate();
+        }
+
+        /// 
+        /// Set a light point on a part
+        /// 
+        /// FIXME: Much of this code should probably be in SceneObjectGroup
+        ///
+        /// 
+        /// 
+        /// 
+        /// 
+        /// 
+        /// 
+        protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
+        {
+            if (part == null)
+                return;
+
+            if (light)
+            {
+                part.Shape.LightEntry = true;
+                part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
+                part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
+                part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
+                part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f);
+                part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f);
+                part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f);
+            }
+            else
+            {
+                part.Shape.LightEntry = false;
+            }
+
+            part.ParentGroup.HasGroupChanged = true;
+            part.ScheduleFullUpdate();
+        }
+
+        public LSL_Vector llGetColor(int face)
+        {
+            m_host.AddScriptLPS(1);
+            return GetColor(m_host, face);
+        }
+
+        protected LSL_Vector GetColor(SceneObjectPart part, int face)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            Color4 texcolor;
+            LSL_Vector rgb = new LSL_Vector();
+            if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                int i;
+
+                for (i = 0 ; i < GetNumberOfSides(part); i++)
+                {
+                    texcolor = tex.GetFace((uint)i).RGBA;
+                    rgb.x += texcolor.R;
+                    rgb.y += texcolor.G;
+                    rgb.z += texcolor.B;
+                }
+
+                rgb.x /= (float)GetNumberOfSides(part);
+                rgb.y /= (float)GetNumberOfSides(part);
+                rgb.z /= (float)GetNumberOfSides(part);
+
+                return rgb;
+            }
+
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                texcolor = tex.GetFace((uint)face).RGBA;
+                rgb.x = texcolor.R;
+                rgb.y = texcolor.G;
+                rgb.z = texcolor.B;
+
+                return rgb;
+            }
+            else
+            {
+                return new LSL_Vector();
+            }
+        }
+
+        public void llSetTexture(string texture, int face)
+        {
+            m_host.AddScriptLPS(1);
+            SetTexture(m_host, texture, face);
+            ScriptSleep(m_sleepMsOnSetTexture);
+        }
+
+        public void llSetLinkTexture(int linknumber, string texture, int face)
+        {
+            m_host.AddScriptLPS(1);
+
+            List parts = GetLinkParts(linknumber);
+
+            foreach (SceneObjectPart part in parts)
+              SetTexture(part, texture, face);
+
+            ScriptSleep(m_sleepMsOnSetLinkTexture);
+        }
+
+        protected void SetTexture(SceneObjectPart part, string texture, int face)
+        {
+            UUID textureID = new UUID();
+
+            textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
+            if (textureID == UUID.Zero)
+            {
+                if (!UUID.TryParse(texture, out textureID))
+                    return;
+            }
+
+            Primitive.TextureEntry tex = part.Shape.Textures;
+
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
+                texface.TextureID = textureID;
+                tex.FaceTextures[face] = texface;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            else if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (uint i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        tex.FaceTextures[i].TextureID = textureID;
+                    }
+                }
+                tex.DefaultTexture.TextureID = textureID;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        public void llScaleTexture(double u, double v, int face)
+        {
+            m_host.AddScriptLPS(1);
+
+            ScaleTexture(m_host, u, v, face);
+            ScriptSleep(m_sleepMsOnScaleTexture);
+        }
+
+        protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
+                texface.RepeatU = (float)u;
+                texface.RepeatV = (float)v;
+                tex.FaceTextures[face] = texface;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (int i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        tex.FaceTextures[i].RepeatU = (float)u;
+                        tex.FaceTextures[i].RepeatV = (float)v;
+                    }
+                }
+                tex.DefaultTexture.RepeatU = (float)u;
+                tex.DefaultTexture.RepeatV = (float)v;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        public void llOffsetTexture(double u, double v, int face)
+        {
+            m_host.AddScriptLPS(1);
+            OffsetTexture(m_host, u, v, face);
+            ScriptSleep(m_sleepMsOnOffsetTexture);
+        }
+
+        protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
+                texface.OffsetU = (float)u;
+                texface.OffsetV = (float)v;
+                tex.FaceTextures[face] = texface;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (int i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        tex.FaceTextures[i].OffsetU = (float)u;
+                        tex.FaceTextures[i].OffsetV = (float)v;
+                    }
+                }
+                tex.DefaultTexture.OffsetU = (float)u;
+                tex.DefaultTexture.OffsetV = (float)v;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        public void llRotateTexture(double rotation, int face)
+        {
+            m_host.AddScriptLPS(1);
+            RotateTexture(m_host, rotation, face);
+            ScriptSleep(m_sleepMsOnRotateTexture);
+        }
+
+        protected void RotateTexture(SceneObjectPart part, double rotation, int face)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
+                texface.Rotation = (float)rotation;
+                tex.FaceTextures[face] = texface;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+            if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                for (int i = 0; i < GetNumberOfSides(part); i++)
+                {
+                    if (tex.FaceTextures[i] != null)
+                    {
+                        tex.FaceTextures[i].Rotation = (float)rotation;
+                    }
+                }
+                tex.DefaultTexture.Rotation = (float)rotation;
+                part.UpdateTextureEntry(tex.GetBytes());
+                return;
+            }
+        }
+
+        public LSL_String llGetTexture(int face)
+        {
+            m_host.AddScriptLPS(1);
+            return GetTexture(m_host, face);
+        }
+
+        protected LSL_String GetTexture(SceneObjectPart part, int face)
+        {
+            Primitive.TextureEntry tex = part.Shape.Textures;
+            if (face == ScriptBaseClass.ALL_SIDES)
+            {
+                face = 0;
+            }
+
+            if (face >= 0 && face < GetNumberOfSides(part))
+            {
+                Primitive.TextureEntryFace texface;
+                texface = tex.GetFace((uint)face);
+                string texture = texface.TextureID.ToString();
+
+                lock (part.TaskInventory)
+                {
+                    foreach (KeyValuePair inv in part.TaskInventory)
+                    {
+                        if (inv.Value.AssetID == texface.TextureID)
+                        {
+                            texture = inv.Value.Name.ToString();
+                            break;
+                        }
+                    }
+                }
+
+                return texture;
+            }
+            else
+            {
+                return UUID.Zero.ToString();
+            }
+        }
+
+        public void llSetPos(LSL_Vector pos)
+        {
+            m_host.AddScriptLPS(1);
+
+            SetPos(m_host, pos, true);
+
+            ScriptSleep(m_sleepMsOnSetPos);
+        }
+
+        /// 
+        /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos
+        /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into.
+        /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking.
+        /// 
+        /// 
+        /// 1 if successful, 0 otherwise.
+        public LSL_Integer llSetRegionPos(LSL_Vector pos)
+        {
+            m_host.AddScriptLPS(1);
+
+            // BEGIN WORKAROUND
+            // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
+            //
+            // This workaround is to prevent silent failure of this function.
+            // According to the specification on the SL Wiki, providing a position outside of the
+            if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
+            {
+                return 0;
+            }
+            // END WORK AROUND
+            else if ( // this is not part of the workaround if-block because it's not related to the workaround.
+                IsPhysical() ||
+                m_host.ParentGroup.IsAttachment || // return FALSE if attachment
+                (
+                    pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
+                    pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
+                    pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
+                    pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
+                    pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
+                )
+            )
+            {
+                return 0;
+            }
+
+            // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range.
+            // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
+
+            Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
+            LandData here = World.GetLandData(objectPos);
+            LandData there = World.GetLandData(pos);
+
+            // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
+
+            bool sameParcel = here.GlobalID == there.GlobalID;
+
+            if (!sameParcel && !World.Permissions.CanRezObject(
+                m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
+            {
+                return 0;
+            }
+
+            SetPos(m_host.ParentGroup.RootPart, pos, false);
+
+            return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0;
+        }
+
+        // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
+        // note linked setpos is capped "differently"
+        private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
+        {
+            if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor)
+                return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start);
+            else
+                return end;
+        }
+
+        protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos)
+        {
+            if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+                return fromPos;
+
+            // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
+
+
+            float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
+            bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
+
+            if (part.ParentGroup.RootPart == part)
+            {
+                if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
+                    targetPos.z = ground;
+            }
+            LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos);
+
+            return real_vec;
+        }
+
+        /// 
+        /// set object position, optionally capping the distance.
+        /// 
+        /// 
+        /// 
+        /// if TRUE, will cap the distance to 10m.
+        protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
+        {
+            // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
+            LSL_Vector currentPos = GetPartLocalPos(part);
+
+            float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
+            bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
+
+            if (part.ParentGroup.RootPart == part)
+            {
+                if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
+                    targetPos.z = ground;
+                SceneObjectGroup parent = part.ParentGroup;
+                parent.UpdateGroupPosition(!adjust ? targetPos :
+                    SetPosAdjust(currentPos, targetPos));
+            }
+            else
+            {
+                part.OffsetPosition = !adjust ? targetPos :
+                    SetPosAdjust(currentPos, targetPos);
+                SceneObjectGroup parent = part.ParentGroup;
+                parent.HasGroupChanged = true;
+                parent.ScheduleGroupForTerseUpdate();
+            }
+        }
+
+        public LSL_Vector llGetPos()
+        {
+            m_host.AddScriptLPS(1);
+            return m_host.GetWorldPosition();
+        }
+
+        public LSL_Vector llGetLocalPos()
+        {
+            m_host.AddScriptLPS(1);
+            return GetPartLocalPos(m_host);
+        }
+
+        protected LSL_Vector GetPartLocalPos(SceneObjectPart part)
+        {
+            m_host.AddScriptLPS(1);
+
+            Vector3 pos;
+
+            if (!part.IsRoot)
+            {
+                pos = part.OffsetPosition;
+            }
+            else
+            {
+                if (part.ParentGroup.IsAttachment)
+                {
+                    pos = part.AttachedPos;
+                }
+                else
+                {
+                    pos = part.AbsolutePosition;
+                }
+            }
+
+//            m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
+
+            return new LSL_Vector(pos);
+        }
+
+        public void llSetRot(LSL_Rotation rot)
+        {
+            m_host.AddScriptLPS(1);
+
+            // try to let this work as in SL...
+            if (m_host.ParentID == 0)
+            {
+                // special case: If we are root, rotate complete SOG to new rotation
+                SetRot(m_host, rot);
+            }
+            else
+            {
+                // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
+                SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
+                if (rootPart != null) // better safe than sorry
+                {
+                    SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
+                }
+            }
+
+            ScriptSleep(m_sleepMsOnSetRot);
+        }
+
+        public void llSetLocalRot(LSL_Rotation rot)
+        {
+            m_host.AddScriptLPS(1);
+            SetRot(m_host, rot);
+            ScriptSleep(m_sleepMsOnSetLocalRot);
+        }
+
+        protected void SetRot(SceneObjectPart part, Quaternion rot)
+        {
+            part.UpdateRotation(rot);
+            // Update rotation does not move the object in the physics scene if it's a linkset.
+
+//KF:  Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type
+//          part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
+
+            // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
+            // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
+            // It's perfectly okay when the object is not an active physical body though.
+            // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
+            // but only if the object is not physial and active.   This is important for rotating doors.
+            // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
+            // scene
+            PhysicsActor pa = part.PhysActor;
+
+            if (pa != null && !pa.IsPhysical)
+            {
+                part.ParentGroup.ResetChildPrimPhysicsPositions();
+            }
+        }
+
+        /// 
+        /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
+        /// 
+        public LSL_Rotation llGetRot()
+        {
+            // unlinked or root prim then use llRootRotation
+            // see llRootRotaion for references.
+            if (m_host.LinkNum == 0 || m_host.LinkNum == 1)
+            {
+                return llGetRootRotation();
+            }
+
+            m_host.AddScriptLPS(1);
+            Quaternion q = m_host.GetWorldRotation();
+            return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
+        }
+
+        private LSL_Rotation GetPartRot(SceneObjectPart part)
+        {
+            Quaternion q;
+            if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim
+            {
+                if (part.ParentGroup.AttachmentPoint != 0)
+                {
+                    ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
+                    if (avatar != null)
+                    {
+                        if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
+                            q = avatar.CameraRotation; // Mouselook
+                        else
+                            q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
+                    }
+                    else
+                        q = part.ParentGroup.GroupRotation; // Likely never get here but just in case
+                }
+                else
+                    q = part.ParentGroup.GroupRotation; // just the group rotation
+
+                return new LSL_Rotation(q);
+            }
+
+            return new LSL_Rotation(part.GetWorldRotation());
+        }
+
+        public LSL_Rotation llGetLocalRot()
+        {
+            m_host.AddScriptLPS(1);
+
+            return new LSL_Rotation(m_host.RotationOffset);
+        }
+
+        public void llSetForce(LSL_Vector force, int local)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (!m_host.ParentGroup.IsDeleted)
+            {
+                if (local != 0)
+                    force *= llGetRot();
+
+                m_host.ParentGroup.RootPart.SetForce(force);
+            }
+        }
+
+        public LSL_Vector llGetForce()
+        {
+            LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
+
+            m_host.AddScriptLPS(1);
+
+            if (!m_host.ParentGroup.IsDeleted)
+            {
+                force = m_host.ParentGroup.RootPart.GetForce();
+            }
+
+            return force;
+        }
+
+        public void llSetVelocity(LSL_Vector velocity, int local)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (!m_host.ParentGroup.IsDeleted)
+            {
+                if (local != 0)
+                    velocity *= llGetRot();
+
+                m_host.ParentGroup.RootPart.Velocity = velocity;
+            }
+        }
+
+        public void llSetAngularVelocity(LSL_Vector angularVelocity, int local)
+        {
+            m_host.AddScriptLPS(1);
+
+            if (!m_host.ParentGroup.IsDeleted)
+            {
+                if (local != 0)
+                    angularVelocity *= llGetRot();
+
+                m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity;
+            }
+        }
+
+        public LSL_Integer llTarget(LSL_Vector position, double range)
+        {
+            m_host.AddScriptLPS(1);
+            return m_host.ParentGroup.registerTargetWaypoint(position,
+                (float)range);
+        }
+
+        public void llTargetRemove(int number)
+        {
+            m_host.AddScriptLPS(1);
+            m_host.ParentGroup.unregisterTargetWaypoint(number);
+        }
+
+        public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
+        {
+            m_host.AddScriptLPS(1);
+            return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
+        }
+
+        public void llRotTargetRemove(int number)
+        {
+            m_host.AddScriptLPS(1);
+            m_host.ParentGroup.unregisterRotTargetWaypoint(number);
+        }
+
+        public void llMoveToTarget(LSL_Vector target, double tau)
+        {
+            m_host.AddScriptLPS(1);
+            m_host.MoveToTarget(target, (float)tau);
+        }
+
+        public void llStopMoveToTarget()
+        {
+            m_host.AddScriptLPS(1);
+            m_host.StopMoveToTarget();
+        }
+
+        public void llApplyImpulse(LSL_Vector force, int local)
+        {
+            m_host.AddScriptLPS(1);
+            //No energy force yet
+            Vector3 v = force;
+            if (v.Length() > 20000.0f)
+            {
+                v.Normalize();
+                v = v * 20000.0f;
+            }
+            m_host.ApplyImpulse(v, local != 0);
+        }
+
+        public void llApplyRotationalImpulse(LSL_Vector force, int local)
+        {
+            m_host.AddScriptLPS(1);
+            m_host.ApplyAngularImpulse(force, local != 0);
+        }
+
+        public void llSetTorque(LSL_Vector torque, int local)
+        {
+            m_host.AddScriptLPS(1);
+            m_host.SetAngularImpulse(torque, local != 0);
+        }
+
+        public LSL_Vector llGetTorque()
+        {
+            m_host.AddScriptLPS(1);
+
+            return new LSL_Vector(m_host.ParentGroup.GetTorque());
+        }
+
+        public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
+        {
+            m_host.AddScriptLPS(1);
+            llSetForce(force, local);
+            llSetTorque(torque, local);
+        }
+
+        public LSL_Vector llGetVel()
+        {
+            m_host.AddScriptLPS(1);
+
+            Vector3 vel;
+
+            if (m_host.ParentGroup.IsAttachment)
+            {
+                ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
+                vel = avatar.GetWorldVelocity();
+            }
+            else
+            {
+                vel = m_host.Velocity;
+            }
+
+            return new LSL_Vector(vel);
+        }
+
+        public LSL_Vector llGetAccel()
+        {
+            m_host.AddScriptLPS(1);
+
+            return new LSL_Vector(m_host.Acceleration);
+        }
+
+        public LSL_Vector llGetOmega()
+        {
+            m_host.AddScriptLPS(1);
+
+            return new LSL_Vector(m_host.AngularVelocity);
+        }
+
+        public LSL_Float llGetTimeOfDay()
+        {
+            m_host.AddScriptLPS(1);
+            return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
+        }
+
+        public LSL_Float llGetWallclock()
+        {
+            m_host.AddScriptLPS(1);
+            return DateTime.Now.TimeOfDay.TotalSeconds;
+        }
+
+        public LSL_Float llGetTime()
+        {
+            m_host.AddScriptLPS(1);
+            TimeSpan ScriptTime = DateTime.Now - m_timer;
+            return (double)(ScriptTime.TotalMilliseconds / 1000);
+        }
+
+        public void llResetTime()
+        {
+            m_host.AddScriptLPS(1);
+            m_timer = DateTime.Now;
+        }
+
+        public LSL_Float llGetAndResetTime()
+        {
+            m_host.AddScriptLPS(1);
+            TimeSpan ScriptTime = DateTime.Now - m_timer;
+            m_timer = DateTime.Now;
+            return (double)(ScriptTime.TotalMilliseconds / 1000);
+        }
+
+        public void llSound(string sound, double volume, int queue, int loop)
+        {
+            m_host.AddScriptLPS(1);
+            Deprecated("llSound", "Use llPlaySound instead");
+        }
+
+        // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
+        // 20080530 Updated to remove code duplication
+        public void llPlaySound(string sound, double volume)
+        {
+            m_host.AddScriptLPS(1);
+
+            // send the sound, once, to all clients in range
+            if (m_SoundModule != null)
+            {
+                m_SoundModule.SendSound(
+                    m_host.UUID,
+                    ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), 
+                    volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
+                    0, false, false);
+            }
+        }
+
+        public void llLoopSound(string sound, double volume)
+        {
+            m_host.AddScriptLPS(1);
+            if (m_SoundModule != null)
+            {
+                m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
+                        volume, 20, false);
+            }
+        }
+
+        public void llLoopSoundMaster(string sound, double volume)
+        {
+            m_host.AddScriptLPS(1);
+            if (m_SoundModule != null)
+            {
+                m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
+                        volume, 20, true);
+            }
+        }
+
+        public void llLoopSoundSlave(string sound, double volume)
+        {
+            m_host.AddScriptLPS(1);
+            lock (m_host.ParentGroup.LoopSoundSlavePrims)
+            {
+                m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host);
+            }
+        }
+
+        public void llPlaySoundSlave(string sound, double volume)
+        {
+            m_host.AddScriptLPS(1);
+
+            // send the sound, once, to all clients in range
+            if (m_SoundModule != null)
+            {
+                m_SoundModule.SendSound(m_host.UUID,
+                        ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
+                        0, true, false);
+            }
+        }
+
+        public void llTriggerSound(string sound, double volume)
+        {
+            m_host.AddScriptLPS(1);
+            // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
+            if (m_SoundModule != null)
+            {
+                m_SoundModule.SendSound(m_host.UUID,
+                        ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0,
+                        false, false);
+            }
+        }
+
+        public void llStopSound()
+        {
+            m_host.AddScriptLPS(1);
+
+            if (m_SoundModule != null)
+                m_SoundModule.StopSound(m_host.UUID);
+        }
+
+        public void llPreloadSound(string sound)
+        {
+            m_host.AddScriptLPS(1);
+            if (m_SoundModule != null)
+                m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
+            ScriptSleep(m_sleepMsOnPreloadSound);
+        }
+
+        /// 
+        /// Return a portion of the designated string bounded by
+        /// inclusive indices (start and end). As usual, the negative
+        /// indices, and the tolerance for out-of-bound values, makes
+        /// this more complicated than it might otherwise seem.
+        /// 
+        public LSL_String llGetSubString(string src, int start, int end)
+        {
+            m_host.AddScriptLPS(1);
+
+            // Normalize indices (if negative).
+            // After normlaization they may still be
+            // negative, but that is now relative to
+            // the start, rather than the end, of the
+            // sequence.
+
+            if (start < 0)
+            {
+                start = src.Length+start;
+            }
+            if (end < 0)
+            {
+                end = src.Length+end;
+            }
+
+            // Conventional substring
+            if (start <= end)
+            {
+                // Implies both bounds are out-of-range.
+                if (end < 0 || start >= src.Length)
+                {
+                    return String.Empty;
+                }
+                // If end is positive, then it directly
+                // corresponds to the lengt of the substring
+                // needed (plus one of course). BUT, it
+                // must be within bounds.
+                if (end >= src.Length)
+                {
+                    end = src.Length-1;
+                }
+
+                if (start < 0)
+                {
+                    return src.Substring(0,end+1);
+                }
+                // Both indices are positive
+                return src.Substring(start, (end+1) - start);
+            }
+
+            // Inverted substring (end < start)
+            else
+            {
+                // Implies both indices are below the
+                // lower bound. In the inverted case, that
+                // means the entire string will be returned
+                // unchanged.
+                if (start < 0)
+                {
+                    return src;
+                }
+                // If both indices are greater than the upper
+                // bound the result may seem initially counter
+                // intuitive.
+                if (end >= src.Length)
+                {
+                    return src;
+                }
+
+                if (end < 0)
+                {
+                    if (start < src.Length)
+                    {
+                        return src.Substring(start);
+                    }
+                    else
+                    {
+                        return String.Empty;
+                    }
+                }
+                else
+                {
+                    if (start < src.Length)
+                    {
+                        return src.Substring(0,end+1) + src.Substring(start);
+                    }
+                    else
+                    {
+                        return src.Substring(0,end+1);
+                    }
+                }
+            }
+         }
+
+        /// 
+        /// Delete substring removes the specified substring bounded
+        /// by the inclusive indices start and end. Indices may be
+        /// negative (indicating end-relative) and may be inverted,
+        /// i.e. end < start.
+        /// 
+        public LSL_String llDeleteSubString(string src, int start, int end)
+        {
+            m_host.AddScriptLPS(1);
+
+            // Normalize indices (if negative).
+            // After normlaization they may still be
+            // negative, but that is now relative to
+            // the start, rather than the end, of the
+            // sequence.
+            if (start < 0)
+            {
+                start = src.Length+start;
+            }
+            if (end < 0)
+            {
+                end = src.Length+end;
+            }
+            // Conventionally delimited substring
+            if (start <= end)
+            {
+                // If both bounds are outside of the existing
+                // string, then return unchanges.
+                if (end < 0 || start >= src.Length)
+                {
+                    return src;
+                }
+                // At least one bound is in-range, so we
+                // need to clip the out-of-bound argument.
+                if (start < 0)
+                {
+                    start = 0;
+                }
+
+                if (end >= src.Length)
+                {
+                    end = src.Length-1;
+                }
+
+                return src.Remove(start,end-start+1);
+            }
+            // Inverted substring
+            else
+            {
+                // In this case, out of bounds means that
+                // the existing string is part of the cut.
+                if (start < 0 || end >= src.Length)
+                {
+                    return String.Empty;
+                }
+
+                if (end > 0)
+                {
+                    if (start < src.Length)
+                    {
+                        return src.Remove(start).Remove(0,end+1);
+                    }
+                    else
+                    {
+                        return src.Remove(0,end+1);
+                    }
+                }
+                else
+                {
+                    if (start < src.Length)
+                    {
+                        return src.Remove(start);
+                    }
+                    else
+                    {
+                        return src;
+                    }
+                }
+            }
+        }
+
+        /// 
+        /// Insert string inserts the specified string identified by src
+        /// at the index indicated by index. Index may be negative, in
+        /// which case it is end-relative. The index may exceed either
+        /// string bound, with the result being a concatenation.
+        /// 
+        public LSL_String llInsertString(string dest, int index, string src)
+        {
+            m_host.AddScriptLPS(1);
+
+            // Normalize indices (if negative).
+            // After normlaization they may still be
+            // negative, but that is now relative to
+            // the start, rather than the end, of the
+            // sequence.
+            if (index < 0)
+            {
+                index = dest.Length+index;
+
+                // Negative now means it is less than the lower
+                // bound of the string.
+
+                if (index < 0)
+                {
+                    return src+dest;
+                }
+
+            }
+
+            if (index >= dest.Length)
+            {
+                return dest+src;
+            }
+
+            // The index is in bounds.
+            // In this case the index refers to the index that will
+            // be assigned to the first character of the inserted string.
+            // So unlike the other string operations, we do not add one
+            // to get the correct string length.
+            return dest.Substring(0,index)+src+dest.Substring(index);
+
+        }
+
+        public LSL_String llToUpper(string src)
+        {
+            m_host.AddScriptLPS(1);
+            return src.ToUpper();
+        }
+
+        public LSL_String llToLower(string src)
+        {
+            m_host.AddScriptLPS(1);
+            return src.ToLower();
+        }
+
+        public void llGiveMoney(string destination, int amount)
+        {
+            Util.FireAndForget(x =>
+            {
+                m_host.AddScriptLPS(1);
+
+                if (m_item.PermsGranter == UUID.Zero)
+                    return;
+
+                if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
+                {
+                    Error("llGiveMoney", "No permissions to give money");
+                    return;
+                }
+
+                UUID toID = new UUID();
+
+                if (!UUID.TryParse(destination, out toID))
+                {
+                    Error("llGiveMoney", "Bad key in llGiveMoney");
+                    return;
+                }
+
+                IMoneyModule money = World.RequestModuleInterface();
+
+                if (money == null)
+                {
+                    NotImplemented("llGiveMoney");
+                    return;
+                }
+
+                money.ObjectGiveMoney(
+                    m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
+            }, null, "LSL_Api.llGiveMoney");
+        }
+
+        public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
+        {
+            m_host.AddScriptLPS(1);
+            Deprecated("llMakeExplosion", "Use llParticleSystem instead");
+            ScriptSleep(m_sleepMsOnMakeExplosion);
+        }
+
+        public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
+        {
+            m_host.AddScriptLPS(1);
+            Deprecated("llMakeFountain", "Use llParticleSystem instead");
+            ScriptSleep(m_sleepMsOnMakeFountain);
+        }
+
+        public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
+        {
+            m_host.AddScriptLPS(1);
+            Deprecated("llMakeSmoke", "Use llParticleSystem instead");
+            ScriptSleep(m_sleepMsOnMakeSmoke);
+        }
+
+        public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
+        {
+            m_host.AddScriptLPS(1);
+            Deprecated("llMakeFire", "Use llParticleSystem instead");
+            ScriptSleep(m_sleepMsOnMakeFire);
+        }
+
+        public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
+        {
+            m_host.AddScriptLPS(1);
+
+            Util.FireAndForget(x =>
+            {
+                if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
+                    return;
+
+                float dist = (float)llVecDist(llGetPos(), pos);
+
+                if (dist > m_ScriptDistanceFactor * 10.0f)
+                    return;
+
+                TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
+
+                if (item == null)
+                {
+                    Error("llRezAtRoot", "Can't find object '" + inventory + "'");
+                    return;
+                }
+
+                if (item.InvType != (int)InventoryType.Object)
+                {
+                    Error("llRezAtRoot", "Can't create requested object; object is missing from database");
+                    return;
+                }
+
+                // need the magnitude later
+                // float velmag = (float)Util.GetMagnitude(llvel);
+
+                List new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
+
+                // If either of these are null, then there was an unknown error.
+                if (new_groups == null)
+                    return;
+
+                foreach (SceneObjectGroup group in new_groups)
+                {
+                    // objects rezzed with this method are die_at_edge by default.
+                    group.RootPart.SetDieAtEdge(true);
+
+                    group.ResumeScripts();
+
+                    m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
+                            "object_rez", new Object[] {
+                            new LSL_String(
+                            group.RootPart.UUID.ToString()) },
+                            new DetectParams[0]));
+
+                    float groupmass = group.GetMass();
+
+                    PhysicsActor pa = group.RootPart.PhysActor;
+
+                    //Recoil.
+                    if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
+                    {
+                        Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
+                        if (recoil != Vector3.Zero)
+                        {
+                            llApplyImpulse(recoil, 0);
+                        }
+                    }
+                    // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
+                }
+            }, null, "LSL_Api.llRezAtRoot");
+
+            //ScriptSleep((int)((groupmass * velmag) / 10));
+            ScriptSleep(m_sleepMsOnRezAtRoot);
+        }
+
+        public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
+        {
+            llRezAtRoot(inventory, pos, vel, rot, param);
+        }
+
+        public void llLookAt(LSL_Vector target, double strength, double damping)
+        {
+            m_host.AddScriptLPS(1);
+            // Determine where we are looking from
+            LSL_Vector from = llGetPos();
+
+            // normalized direction to target
+            LSL_Vector dir = llVecNorm(target - from);
+            // use vertical to help compute left axis
+            LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
+            // find normalized left axis parallel to horizon
+            LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
+            // make up orthogonal to left and dir
+            up = LSL_Vector.Cross(dir, left);
+
+            // compute rotation based on orthogonal axes
+            LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up);
+
+            // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
+            // set the rotation of the object, copy that behavior
+            PhysicsActor pa = m_host.PhysActor;
+
+            if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical)
+            {
+                llSetRot(rot);
+            }
+            else
+            {
+                m_host.StartLookAt(rot, (float)strength, (float)damping);
+            }
+        }
+
+        public void llStopLookAt()
+        {
+            m_host.AddScriptLPS(1);
+            m_host.StopLookAt();
+        }
+
+        public void llSetTimerEvent(double sec)
+        {
+            if (sec != 0.0 && sec < m_MinTimerInterval)
+                sec = m_MinTimerInterval;
+            m_host.AddScriptLPS(1);
+            // Setting timer repeat
+            AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec);
+        }
+
+        public virtual void llSleep(double sec)
+        {
+//            m_log.Info("llSleep snoozing " + sec + "s.");
+            m_host.AddScriptLPS(1);
+
+            Sleep((int)(sec * 1000));
+        }
+
+        public LSL_Float llGetMass()
+        {
+            m_host.AddScriptLPS(1);
+
+            if (m_host.ParentGroup.IsAttachment)
+            {
+                ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
+
+                if (attachedAvatar != null)
+                {
+                    return attachedAvatar.GetMass();
+                }
+                else
+                {
+                    return 0;
+                }
+            }
+            else
+            {
+                if (m_host.IsRoot)
+                {
+                    return m_host.ParentGroup.GetMass();
+                }
+                else
+                {
+                    return m_host.GetMass();
+                }
+            }
+        }
+
+        public LSL_Float llGetMassMKS()
+        {
+            // this is what the wiki says it does!
+            // http://wiki.secondlife.com/wiki/LlGetMassMKS
+            return llGetMass() * 100.0;
+        }
+
+        public void llCollisionFilter(string name, string id, int accept)
+        {
+            m_host.AddScriptLPS(1);
+            m_host.CollisionFilter.Clear();
+            UUID objectID;
+
+            if (!UUID.TryParse(id, out objectID))
+                objectID = UUID.Zero;
+
+            if (objectID == UUID.Zero && name == "")
+                return;
+
+            m_host.CollisionFilter.Add(accept,objectID.ToString() + name);
+        }
+
+        public void llTakeControls(int controls, int accept, int pass_on)
+        {
+            if (m_item.PermsGranter != UUID.Zero)
+            {
+                ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
+
+                if (presence != null)
+                {
+                    if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
+                    {
+                        presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID);
+                    }
+                }
+            }
+
+            m_host.AddScriptLPS(1);
+        }
+
+        public void llReleaseControls()
+        {
+            m_host.AddScriptLPS(1);
+
+            if (m_item.PermsGranter != UUID.Zero)
+            {
+                ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
+
+                if (presence != null)
+                {
+                    if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
+                    {
+                        // Unregister controls from Presence
+                        presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
+                        // Remove Take Control permission.
+                        m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
+                    }
+                }
+            }
+        }
+
+        public void llReleaseURL(string url)
+        {
+            m_host.AddScriptLPS(1);
+            if (m_UrlModule != null)
+                m_UrlModule.ReleaseURL(url);
+        }
+
+        /// 
+        /// Attach the object containing this script to the avatar that owns it.
+        /// 
+        /// 
+        /// The attachment point (e.g. ATTACH_CHEST)
+        /// 
+        /// true if the attach suceeded, false if it did not
+        public bool AttachToAvatar(int attachmentPoint)
+        {
+            SceneObjectGroup grp = m_host.ParentGroup;
+            ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
+
+            IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
+
+            if (attachmentsModule != null)
+                return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true);
+            else
+                return false;
+        }
+
+        /// 
+        /// Detach the object containing this script from the avatar it is attached to.
+        /// 
+        /// 
+        /// Nothing happens if the object is not attached.
+        /// 
+        public void DetachFromAvatar()
+        {
+            Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar");
+        }
+
+        private void DetachWrapper(object o)
+        {
+            if (World.AttachmentsModule != null)
+            {
+                SceneObjectPart host = (SceneObjectPart)o;
+                ScenePresence presence = World.GetScenePresence(host.OwnerID);
+                World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup);
+            }
+        }
+
+        public void llAttachToAvatar(int attachmentPoint)
+        {
+            m_host.AddScriptLPS(1);
+
+//            if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
+//                return;
+
+            if (m_item.PermsGranter != m_host.OwnerID)
+                return;
+
+            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
+                AttachToAvatar(attachmentPoint);
+        }
+
+        public void llDetachFromAvatar()
+        {
+            m_host.AddScriptLPS(1);
+
+            if (m_host.ParentGroup.AttachmentPoint == 0)
+                return;
+
+            if (m_item.PermsGranter != m_host.OwnerID)
+                return;
+
+            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
+                DetachFromAvatar();
+        }
+
+        public void llTakeCamera(string avatar)
+        {
+            m_host.AddScriptLPS(1);
+            Deprecated("llTakeCamera", "Use llSetCameraParams instead");
+        }
+
+        public void llReleaseCamera(string avatar)
+        {
+            m_host.AddScriptLPS(1);
+            Deprecated("llReleaseCamera", "Use llClearCameraParams instead");
+        }
+
+        public LSL_String llGetOwner()
+        {
+            m_host.AddScriptLPS(1);
+
+            return m_host.OwnerID.ToString();
+        }
+
+        public void llInstantMessage(string user, string message)
+        {
+            m_host.AddScriptLPS(1);
+
+            // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
+            // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
+            // but I don't think we have a list of scenes available from here.
+            // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
+
+            // user is a UUID
+
+            // TODO: figure out values for client, fromSession, and imSessionID
+            // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
+
+            GridInstantMessage msg = new GridInstantMessage();
             msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid;
-            msg.toAgentID = new Guid(user); // toAgentID.Guid;
-            msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here
-//            m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
-//            m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
-            msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
-            //if (client != null)
-            //{
-                msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
-            //}
-            //else
-            //{
-            //    msg.fromAgentName = "(hippos)";// Added for posterity.  This means that we can't figure out who sent it
-            //}
-            // Cap the message length at 1024.
-            if (message != null && message.Length > 1024)
-                msg.message = message.Substring(0, 1024);
-            else
-                msg.message = message;
-            msg.dialog = (byte)19; // messgage from script ??? // dialog;
-            msg.fromGroup = false;// fromGroup;
-            msg.offline = (byte)0; //offline;
-            msg.ParentEstateID = 0; //ParentEstateID;
-            msg.Position = new Vector3(m_host.AbsolutePosition);
-            msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
-
-            Vector3 pos = m_host.AbsolutePosition;
-            msg.binaryBucket
-                = Util.StringToBytes256(
-                    "{0}/{1}/{2}/{3}",
-                    World.RegionInfo.RegionName,
-                    (int)Math.Floor(pos.X),
-                    (int)Math.Floor(pos.Y),
-                    (int)Math.Floor(pos.Z));
-
-            if (m_TransferModule != null)
-            {
-                m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
-            }
-
-            ScriptSleep(m_sleepMsOnInstantMessage);
-      }
-
-        public void llEmail(string address, string subject, string message)
-        {
-            m_host.AddScriptLPS(1);
-            IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface();
-            if (emailModule == null)
-            {
-                Error("llEmail", "Email module not configured");
-                return;
-            }
-
-            //Restrict email destination to the avatars registered email address?
-            //The restriction only applies if the destination address is not local.
-            if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false)
-            {
-                UserAccount account =
-                        World.UserAccountService.GetUserAccount(
-                            World.RegionInfo.ScopeID,
-                            m_host.OwnerID);
-
-                if (account == null)
-                {
-                    Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'");
-                    return;
-                }
-
-                if (String.IsNullOrEmpty(account.Email))
-                {
-                    Error("llEmail", "User account has not registered an email address.");
-                    return;
-                }
-
-                address = account.Email;
-            }
-
-            emailModule.SendEmail(m_host.UUID, address, subject, message);
-            ScriptSleep(m_sleepMsOnEmail);
-        }
-
-        public void llGetNextEmail(string address, string subject)
-        {
-            m_host.AddScriptLPS(1);
-            IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface();
-            if (emailModule == null)
-            {
-                Error("llGetNextEmail", "Email module not configured");
-                return;
-            }
-            Email email;
-
-            email = emailModule.GetNextEmail(m_host.UUID, address, subject);
-
-            if (email == null)
-                return;
-
-            m_ScriptEngine.PostObjectEvent(m_host.LocalId,
-                    new EventParams("email",
-                    new Object[] {
-                        new LSL_String(email.time),
-                        new LSL_String(email.sender),
-                        new LSL_String(email.subject),
-                        new LSL_String(email.message),
-                        new LSL_Integer(email.numLeft)},
-                    new DetectParams[0]));
-
-        }
-
-        public LSL_String llGetKey()
-        {
-            m_host.AddScriptLPS(1);
-            return m_host.UUID.ToString();
-        }
-
-        public LSL_Key llGenerateKey()
-        {
-            m_host.AddScriptLPS(1);
-            return UUID.Random().ToString();
-        }
-
-        public void llSetBuoyancy(double buoyancy)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (!m_host.ParentGroup.IsDeleted)
-            {
-                m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
-            }
-        }
-
-        /// 
-        /// Attempt to clamp the object on the Z axis at the given height over tau seconds.
-        /// 
-        /// Height to hover.  Height of zero disables hover.
-        /// False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher
-        /// Number of seconds over which to reach target
-        public void llSetHoverHeight(double height, int water, double tau)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_host.PhysActor != null)
-            {
-                PIDHoverType hoverType = PIDHoverType.Ground;
-                if (water != 0)
-                {
-                    hoverType = PIDHoverType.GroundAndWater;
-                }
-
-                m_host.SetHoverHeight((float)height, hoverType, (float)tau);
-            }
-        }
-
-        public void llStopHover()
-        {
-            m_host.AddScriptLPS(1);
-            if (m_host.PhysActor != null)
-            {
-                m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
-            }
-        }
-
-        public void llMinEventDelay(double delay)
-        {
-            m_host.AddScriptLPS(1);
-            try
-            {
-                m_ScriptEngine.SetMinEventDelay(m_item.ItemID, delay);
-            }
-            catch (NotImplementedException)
-            {
-                // Currently not implemented in DotNetEngine only XEngine
-                NotImplemented("llMinEventDelay", "In DotNetEngine");
-            }
-        }
-
-        public void llSoundPreload(string sound)
-        {
-            m_host.AddScriptLPS(1);
-            Deprecated("llSoundPreload", "Use llPreloadSound instead");
-        }
-
-        public void llRotLookAt(LSL_Rotation target, double strength, double damping)
-        {
-            m_host.AddScriptLPS(1);
-
-            // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
-            // set the rotation of the object, copy that behavior
-            PhysicsActor pa = m_host.PhysActor;
-
-            if (strength == 0 || pa == null || !pa.IsPhysical)
-            {
-                llSetLocalRot(target);
-            }
-            else
-            {
-                m_host.RotLookAt(target, (float)strength, (float)damping);
-            }
-        }
-
-        public LSL_Integer llStringLength(string str)
-        {
-            m_host.AddScriptLPS(1);
-            if (str.Length > 0)
-            {
-                return str.Length;
-            }
-            else
-            {
-                return 0;
-            }
-        }
-
-        public void llStartAnimation(string anim)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_item.PermsGranter == UUID.Zero)
-                return;
-
-            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
-            {
-                ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
-
-                if (presence != null)
-                {
-                    // Do NOT try to parse UUID, animations cannot be triggered by ID
-                    UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
-                    if (animID == UUID.Zero)
-                        presence.Animator.AddAnimation(anim, m_host.UUID);
-                    else
-                        presence.Animator.AddAnimation(animID, m_host.UUID);
-                }
-            }
-        }
-
-        public void llStopAnimation(string anim)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_item.PermsGranter == UUID.Zero)
-                return;
-
-            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
-            {
-                ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
-
-                if (presence != null)
-                {
-                    UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim);
-
-                    if (animID == UUID.Zero)
-                        presence.Animator.RemoveAnimation(anim);
-                    else
-                        presence.Animator.RemoveAnimation(animID, true);
-                }
-            }
-        }
-
-        public void llPointAt(LSL_Vector pos)
-        {
-            m_host.AddScriptLPS(1);
-        }
-
-        public void llStopPointAt()
-        {
-            m_host.AddScriptLPS(1);
-        }
-
-        public void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
-        {
-            m_host.AddScriptLPS(1);
-            TargetOmega(m_host, axis, spinrate, gain);
-        }
-
-        protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
-        {
-            PhysicsActor pa = part.PhysActor;
-            if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d )
-                spinrate = 0.0d;
-            part.UpdateAngularVelocity(axis * spinrate);
-         }
-
-        public LSL_Integer llGetStartParameter()
-        {
-            m_host.AddScriptLPS(1);
-            return m_ScriptEngine.GetStartParameter(m_item.ItemID);
-        }
-
-        public void llRequestPermissions(string agent, int perm)
-        {
-            UUID agentID;
-
-            if (!UUID.TryParse(agent, out agentID))
-                return;
-
-            if (agentID == UUID.Zero || perm == 0) // Releasing permissions
-            {
-                llReleaseControls();
-
-                m_item.PermsGranter = UUID.Zero;
-                m_item.PermsMask = 0;
-
-                m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
-                        "run_time_permissions", new Object[] {
-                        new LSL_Integer(0) },
-                        new DetectParams[0]));
-
-                return;
-            }
-
-            if (m_item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
-                llReleaseControls();
-
-            m_host.AddScriptLPS(1);
-
-            int implicitPerms = 0;
-
-            if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar)
-            {
-                // When attached, certain permissions are implicit if requested from owner
-                implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
-                        ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
-                        ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
-                        ScriptBaseClass.PERMISSION_TRACK_CAMERA |
-                        ScriptBaseClass.PERMISSION_ATTACH;
-            }
-            else
-            {
-                if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null)
-                {
-                    // When agent is sitting, certain permissions are implicit if requested from sitting agent
-                    implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
-                        ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
-                        ScriptBaseClass.PERMISSION_TRACK_CAMERA |
-                        ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
-                }
-                else
-                {
-                    if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
-                        implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
-                }
-            }
-
-            if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
-            {
-                lock (m_host.TaskInventory)
-                {
-                    m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
-                    m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
-                }
-
-                m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
-                        "run_time_permissions", new Object[] {
-                        new LSL_Integer(perm) },
-                        new DetectParams[0]));
-
-                return;
-            }
-
-            ScenePresence presence = World.GetScenePresence(agentID);
-            
-            if (presence != null)
-            {
-                // If permissions are being requested from an NPC and were not implicitly granted above then
-                // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner
-                INPCModule npcModule = World.RequestModuleInterface();
-                if (npcModule != null && npcModule.IsNPC(agentID, World))
-                {
-                    if (npcModule.CheckPermissions(agentID, m_host.OwnerID))
-                    {
-                        lock (m_host.TaskInventory)
-                        {
-                            m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
-                            m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
-                        }
-
-                        m_ScriptEngine.PostScriptEvent(
-                            m_item.ItemID,
-                            new EventParams(
-                                "run_time_permissions", new Object[] { new LSL_Integer(perm) }, new DetectParams[0]));
-                    }
-
-                    // it is an NPC, exit even if the permissions werent granted above, they are not going to answer
-                    // the question!
-                    return;
-                }
-
-                string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID);
-                if (ownerName == String.Empty)
-                    ownerName = "(hippos)";
-
-                if (!m_waitingForScriptAnswer)
-                {
-                    lock (m_host.TaskInventory)
-                    {
-                        m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
-                        m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
-                    }
-
-                    presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
-                    m_waitingForScriptAnswer=true;
-                }
-
-                presence.ControllingClient.SendScriptQuestion(
-                    m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, m_item.ItemID, perm);
-
-                return;
-            }
-
-            // Requested agent is not in range, refuse perms
-            m_ScriptEngine.PostScriptEvent(
-                m_item.ItemID,
-                new EventParams("run_time_permissions", new Object[] { new LSL_Integer(0) }, new DetectParams[0]));
-        }
-
-        void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
-        {
-            if (taskID != m_host.UUID)
-                return;
-
-            client.OnScriptAnswer -= handleScriptAnswer;
-            m_waitingForScriptAnswer = false;
-
-            if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
-                llReleaseControls();
-
-            lock (m_host.TaskInventory)
-            {
-                m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
-            }
-
-            m_ScriptEngine.PostScriptEvent(
-                m_item.ItemID,
-                new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0]));
-        }
-
-        public LSL_String llGetPermissionsKey()
-        {
-            m_host.AddScriptLPS(1);
-
-            return m_item.PermsGranter.ToString();
-        }
-
-        public LSL_Integer llGetPermissions()
-        {
-            m_host.AddScriptLPS(1);
-
-            int perms = m_item.PermsMask;
-
-            if (m_automaticLinkPermission)
-                perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
-
-            return perms;
-        }
-
-        public LSL_Integer llGetLinkNumber()
-        {
-            m_host.AddScriptLPS(1);
-
-            if (m_host.ParentGroup.PrimCount > 1)
-            {
-                return m_host.LinkNum;
-            }
-            else
-            {
-                return 0;
-            }
-        }
-
-        public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
-        {
-            List parts = GetLinkParts(linknumber);
-
-            foreach (SceneObjectPart part in parts)
-                part.SetFaceColorAlpha(face, color, null);
-        }
-
-        public void llCreateLink(string target, int parent)
-        {
-            m_host.AddScriptLPS(1);
-
-            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
-                && !m_automaticLinkPermission)
-            {
-                Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set");
-                return;
-            }
-
-            CreateLink(target, parent);
-        }
-
-        public void CreateLink(string target, int parent)
-        {
-            UUID targetID;
-
-            if (!UUID.TryParse(target, out targetID))
-                return;           
-
-            SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID);
-
-            if (targetPart.ParentGroup.AttachmentPoint != 0)
-                return; // Fail silently if attached
-
-            if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
-                return;
-
-            SceneObjectGroup parentPrim = null, childPrim = null;
-
-            if (targetPart != null)
-            {
-                if (parent != 0)
-                {
-                    parentPrim = m_host.ParentGroup;
-                    childPrim = targetPart.ParentGroup;
-                }
-                else
-                {
-                    parentPrim = targetPart.ParentGroup;
-                    childPrim = m_host.ParentGroup;
-                }
-
-                // Required for linking
-                childPrim.RootPart.ClearUpdateSchedule();
-                parentPrim.LinkToGroup(childPrim, true);
-            }
-
-            parentPrim.TriggerScriptChangedEvent(Changed.LINK);
-            parentPrim.RootPart.CreateSelected = true;
-            parentPrim.HasGroupChanged = true;
-            parentPrim.ScheduleGroupForFullUpdate();
-
-            IClientAPI client = null;
-            ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
-            if (sp != null)
-                client = sp.ControllingClient;
-
-            if (client != null)
-                parentPrim.SendPropertiesToClient(client);
-
-            ScriptSleep(m_sleepMsOnCreateLink);
-        }
-
-        public void llBreakLink(int linknum)
-        {
-            m_host.AddScriptLPS(1);
-
-            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
-                && !m_automaticLinkPermission)
-            {
-                Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set");
-                return;
-            }
-
-            BreakLink(linknum);
-        }
-
-        public void BreakLink(int linknum)
-        {
-            if (linknum < ScriptBaseClass.LINK_THIS)
-                return;
-
-            SceneObjectGroup parentPrim = m_host.ParentGroup;
-
-            if (parentPrim.AttachmentPoint != 0)
-                return; // Fail silently if attached
-            SceneObjectPart childPrim = null;
-
-            switch (linknum)
-            {
-                case ScriptBaseClass.LINK_ROOT:
-                    break;
-                case ScriptBaseClass.LINK_SET:
-                case ScriptBaseClass.LINK_ALL_OTHERS:
-                case ScriptBaseClass.LINK_ALL_CHILDREN:
-                case ScriptBaseClass.LINK_THIS:
-                    foreach (SceneObjectPart part in parentPrim.Parts)
-                    {
-                        if (part.UUID != m_host.UUID)
-                        {
-                            childPrim = part;
-                            break;
-                        }
-                    }
-                    break;
-                default:
-                    childPrim = parentPrim.GetLinkNumPart(linknum);
-                    if (childPrim.UUID == m_host.UUID)
-                        childPrim = null;
-                    break;
-            }
-
-            if (linknum == ScriptBaseClass.LINK_ROOT)
-            {
-                // Restructuring Multiple Prims.
-                List parts = new List(parentPrim.Parts);
-                parts.Remove(parentPrim.RootPart);
-                foreach (SceneObjectPart part in parts)
-                {
-                    parentPrim.DelinkFromGroup(part.LocalId, true);
-                }
-                parentPrim.HasGroupChanged = true;
-                parentPrim.ScheduleGroupForFullUpdate();
-                parentPrim.TriggerScriptChangedEvent(Changed.LINK);
-
-                if (parts.Count > 0)
-                {
-                    SceneObjectPart newRoot = parts[0];
-                    parts.Remove(newRoot);
-                    foreach (SceneObjectPart part in parts)
-                    {
-                        // Required for linking
-                        part.ClearUpdateSchedule();
-                        newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
-                    }
-                    newRoot.ParentGroup.HasGroupChanged = true;
-                    newRoot.ParentGroup.ScheduleGroupForFullUpdate();
-                }
-            }
-            else
-            {
-                if (childPrim == null)
-                    return;
-
-                parentPrim.DelinkFromGroup(childPrim.LocalId, true);
-                parentPrim.HasGroupChanged = true;
-                parentPrim.ScheduleGroupForFullUpdate();
-                parentPrim.TriggerScriptChangedEvent(Changed.LINK);
-            }
-        }
-
-        public void llBreakAllLinks()
-        {
-            m_host.AddScriptLPS(1);
-
-            if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
-                && !m_automaticLinkPermission)
-            {
-                Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set");
-                return;
-            }
-
-            BreakAllLinks();
-        }
-
-        public void BreakAllLinks()
-        {
-            SceneObjectGroup parentPrim = m_host.ParentGroup;
-            if (parentPrim.AttachmentPoint != 0)
-                return; // Fail silently if attached
-
-            List parts = new List(parentPrim.Parts);
-            parts.Remove(parentPrim.RootPart);
-
-            foreach (SceneObjectPart part in parts)
-            {
-                parentPrim.DelinkFromGroup(part.LocalId, true);
-                parentPrim.TriggerScriptChangedEvent(Changed.LINK);
-            }
-            parentPrim.HasGroupChanged = true;
-            parentPrim.ScheduleGroupForFullUpdate();
-        }
-
-        public LSL_String llGetLinkKey(int linknum)
-        {
-            m_host.AddScriptLPS(1);
-
-            ISceneEntity entity = GetLinkEntity(m_host, linknum);
-
-            if (entity != null)
-                return entity.UUID.ToString();
-            else
-                return ScriptBaseClass.NULL_KEY;
-        }
-
-        /// 
-        /// Returns the name of the child prim or seated avatar matching the
-        /// specified link number.
-        /// 
-        /// 
-        /// The number of a link in the linkset or a link-related constant.
-        /// 
-        /// 
-        /// The name determined to match the specified link number.
-        /// 
-        /// 
-        /// The rules governing the returned name are not simple. The only
-        /// time a blank name is returned is if the target prim has a blank
-        /// name. If no prim with the given link number can be found then
-        /// usually NULL_KEY is returned but there are exceptions.
-        ///
-        /// In a single unlinked prim, A call with 0 returns the name, all
-        /// other values for link number return NULL_KEY
-        ///
-        /// In link sets it is more complicated.
-        ///
-        /// If the script is in the root prim:-
-        ///     A zero link number returns NULL_KEY.
-        ///     Positive link numbers return the name of the prim, or NULL_KEY
-        ///     if a prim does not exist at that position.
-        ///     Negative link numbers return the name of the first child prim.
-        ///
-        /// If the script is in a child prim:-
-        ///     Link numbers 0 or 1 return the name of the root prim.
-        ///     Positive link numbers return the name of the prim or NULL_KEY
-        ///     if a prim does not exist at that position.
-        ///     Negative numbers return the name of the root prim.
-        ///
-        /// References
-        /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName
-        /// Mentions NULL_KEY being returned
-        /// http://wiki.secondlife.com/wiki/LlGetLinkName
-        /// Mentions using the LINK_* constants, some of which are negative
-        /// 
-        public LSL_String llGetLinkName(int linknum)
-        {
-            m_host.AddScriptLPS(1);
-
-            ISceneEntity entity = GetLinkEntity(m_host, linknum);
-
-            if (entity != null)
-                return entity.Name;
-            else
-                return ScriptBaseClass.NULL_KEY;
-        }
-
-        public LSL_Integer llGetInventoryNumber(int type)
-        {
-            m_host.AddScriptLPS(1);
-            int count = 0;
-
-            lock (m_host.TaskInventory)
-            {
-                foreach (KeyValuePair inv in m_host.TaskInventory)
-                {
-                    if (inv.Value.Type == type || type == -1)
-                    {
-                        count = count + 1;
-                    }
-                }
-            }
-
-            return count;
-        }
-
-        public LSL_String llGetInventoryName(int type, int number)
-        {
-            m_host.AddScriptLPS(1);
-            ArrayList keys = new ArrayList();
-
-            lock (m_host.TaskInventory)
-            {
-                foreach (KeyValuePair inv in m_host.TaskInventory)
-                {
-                    if (inv.Value.Type == type || type == -1)
-                    {
-                        keys.Add(inv.Value.Name);
-                    }
-                }
-            }
-
-            if (keys.Count == 0)
-            {
-                return String.Empty;
-            }
-            keys.Sort();
-            if (keys.Count > number)
-            {
-                return (string)keys[number];
-            }
-            return String.Empty;
-        }
-
-        public LSL_Float llGetEnergy()
-        {
-            m_host.AddScriptLPS(1);
-            // TODO: figure out real energy value
-            return 1.0f;
-        }
-
-        public void llGiveInventory(string destination, string inventory)
-        {
-            m_host.AddScriptLPS(1);
-
-            UUID destId = UUID.Zero;
-
-            if (!UUID.TryParse(destination, out destId))
-            {
-                Error("llGiveInventory", "Can't parse destination key '" + destination + "'");
-                return;
-            }
-
-            TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
-
-            if (item == null)
-            {
-                Error("llGiveInventory", "Can't find inventory object '" + inventory + "'");
-                return;
-            }
-
-            UUID objId = item.ItemID;
-
-            // check if destination is an object
-            if (World.GetSceneObjectPart(destId) != null)
-            {
-                // destination is an object
-                World.MoveTaskInventoryItem(destId, m_host, objId);
-            }
-            else
-            {
-                ScenePresence presence = World.GetScenePresence(destId);
-
-                if (presence == null)
-                {
-                    UserAccount account =
-                            World.UserAccountService.GetUserAccount(
-                            World.RegionInfo.ScopeID,
-                            destId);
-
-                    if (account == null)
-                    {
-                        GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString());
-                        if(info == null || info.Online == false)
-                        {
-                            Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'");
-                            return;
-                        }
-                    }
-                }
-                // destination is an avatar
-                string message;
-                InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message);
-
-                if (agentItem == null)
-                {
-                    llSay(0, message); 
-                    return;
-                }
-
-                if (m_TransferModule != null)
-                {
-                    byte[] bucket = new byte[1];
-                    bucket[0] = (byte)item.Type;
-
-                    GridInstantMessage msg = new GridInstantMessage(World,
-                            m_host.OwnerID, m_host.Name, destId,
-                            (byte)InstantMessageDialog.TaskInventoryOffered,
-                            false, item.Name+". "+m_host.Name+" is located at "+
-                            World.RegionInfo.RegionName+" "+
-                            m_host.AbsolutePosition.ToString(),
-                            agentItem.ID, true, m_host.AbsolutePosition,
-                            bucket, true);
-
-                    m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
-                }
-
-                ScriptSleep(m_sleepMsOnGiveInventory);
-            }
-        }
-
-        public void llRemoveInventory(string name)
-        {
-            m_host.AddScriptLPS(1);
-
-            TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
-
-            if (item == null)
-                return;
-
-            if (item.ItemID == m_item.ItemID)
-                throw new ScriptDeleteException();
-            else
-                m_host.Inventory.RemoveInventoryItem(item.ItemID);
-        }
-
-        public void llSetText(string text, LSL_Vector color, double alpha)
-        {
-            m_host.AddScriptLPS(1);
-            Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
-            if (text.Length > 254)
-                text = text.Remove(254);
-
-            byte[] data;
-            do
-            {
-                data = Util.UTF8.GetBytes(text);
-                if (data.Length > 254)
-                    text = text.Substring(0, text.Length - 1);
-            } while (data.Length > 254);
-
-            m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
-            //m_host.ParentGroup.HasGroupChanged = true;
-            //m_host.ParentGroup.ScheduleGroupForFullUpdate();
-        }
-
-        public LSL_Float llWater(LSL_Vector offset)
-        {
-            m_host.AddScriptLPS(1);
-            return World.RegionInfo.RegionSettings.WaterHeight;
-        }
-
-        public void llPassTouches(int pass)
-        {
-            m_host.AddScriptLPS(1);
-            if (pass != 0)
-                m_host.PassTouches = true;
-            else
-                m_host.PassTouches = false;
-        }
-
-        public LSL_String llRequestAgentData(string id, int data)
-        {
-            m_host.AddScriptLPS(1);
-
-            UUID uuid = (UUID)id;
-            PresenceInfo pinfo = null;
-            UserAccount account;
-
-            UserInfoCacheEntry ce;
-
-            lock (m_userInfoCache)
-            {
-                if (!m_userInfoCache.TryGetValue(uuid, out ce))
-                {
-                    account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
-                    if (account == null)
-                    {
-                        m_userInfoCache[uuid] = null; // Cache negative
-                        return UUID.Zero.ToString();
-                    }
-
-                    PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
-                    if (pinfos != null && pinfos.Length > 0)
-                    {
-                        foreach (PresenceInfo p in pinfos)
-                        {
-                            if (p.RegionID != UUID.Zero)
-                            {
-                                pinfo = p;
-                            }
-                        }
-                    }
-
-                    ce = new UserInfoCacheEntry();
-                    ce.time = Util.EnvironmentTickCount();
-                    ce.account = account;
-                    ce.pinfo = pinfo;
-
-                    m_userInfoCache[uuid] = ce;
-                }
-                else
-                {
-                    if (ce == null)
-                        return UUID.Zero.ToString();
-
-                    account = ce.account;
-
-                    if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) 
-                        >= LlRequestAgentDataCacheTimeoutMs)
-                    {
-                        PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
-                        if (pinfos != null && pinfos.Length > 0)
-                        {
-                            foreach (PresenceInfo p in pinfos)
-                            {
-                                if (p.RegionID != UUID.Zero)
-                                {
-                                    pinfo = p;
-                                }
-                            }
-                        }
-                        else
-                        {
-                            pinfo = null;
-                        }
-
-                        ce.time = Util.EnvironmentTickCount();
-                        ce.pinfo = pinfo;
-                    }
-                    else
-                    {
-                        pinfo = ce.pinfo;
-                    }
-                }
-            }
-
-            string reply = String.Empty;
-
-            switch (data)
-            {
-            case ScriptBaseClass.DATA_ONLINE:
-                if (pinfo != null && pinfo.RegionID != UUID.Zero)
-                    reply = "1";
-                else
-                    reply = "0";
-                break;
-            case ScriptBaseClass.DATA_NAME: // (First Last)
-                reply = account.FirstName + " " + account.LastName;
-                break;
-            case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD)
-                DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
-                born = born.AddSeconds(account.Created);
-                reply = born.ToString("yyyy-MM-dd");
-                break;
-            case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0)
-                reply = "0,0,0,0,0,0";
-                break;
-            case 7: // DATA_USERLEVEL (integer).  This is not available in LL and so has no constant.
-                reply = account.UserLevel.ToString();
-                break;
-            case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3)
-                reply = "0";
-                break;
-            default:
-                return UUID.Zero.ToString(); // Raise no event
-            }
-
-            UUID rq = UUID.Random();
-
-            UUID tid = AsyncCommands.
-                DataserverPlugin.RegisterRequest(m_host.LocalId,
-                                             m_item.ItemID, rq.ToString());
-
-            AsyncCommands.
-            DataserverPlugin.DataserverReply(rq.ToString(), reply);
-
-            ScriptSleep(m_sleepMsOnRequestAgentData);
-            return tid.ToString();
-        }
-
-        public LSL_String llRequestInventoryData(string name)
-        {
-            m_host.AddScriptLPS(1);
-
-            foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems())
-            {
-                if (item.Type == 3 && item.Name == name)
-                {
-                    UUID tid = AsyncCommands.
-                        DataserverPlugin.RegisterRequest(m_host.LocalId,
-                                                     m_item.ItemID, item.AssetID.ToString());
-
-                    Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
-
-                    World.AssetService.Get(item.AssetID.ToString(), this,
-                        delegate(string i, object sender, AssetBase a)
-                        {
-                            AssetLandmark lm = new AssetLandmark(a);
-
-                            float rx = (uint)(lm.RegionHandle >> 32);
-                            float ry = (uint)lm.RegionHandle;
-                            region = lm.Position + new Vector3(rx, ry, 0) - region;
-
-                            string reply = region.ToString();
-                            AsyncCommands.
-                                DataserverPlugin.DataserverReply(i.ToString(),
-                                                             reply);
-                        });
-
-                    ScriptSleep(m_sleepMsOnRequestInventoryData);
-                    return tid.ToString();
-                }
-            }
-
-            ScriptSleep(m_sleepMsOnRequestInventoryData);
-            return String.Empty;
-        }
-
-        public void llSetDamage(double damage)
-        {
-            m_host.AddScriptLPS(1);
-            m_host.ParentGroup.Damage = (float)damage;
-        }
-
-        public void llTeleportAgentHome(string agent)
-        {
-            m_host.AddScriptLPS(1);
-            UUID agentId = new UUID();
-            if (UUID.TryParse(agent, out agentId))
-            {
-                ScenePresence presence = World.GetScenePresence(agentId);
-                if (presence != null)
-                {
-                    // agent must be over the owners land
-                    if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
-                    {
-                        World.TeleportClientHome(agentId, presence.ControllingClient);
-                    }
-                }
-            }
-
-            ScriptSleep(m_sleepMsOnSetDamage);
-        }
-
-        public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
-        {
-            m_host.AddScriptLPS(1);
-            UUID agentId = new UUID();
-
-            if (UUID.TryParse(agent, out agentId))
-            {
-                ScenePresence presence = World.GetScenePresence(agentId);
-                if (presence != null && presence.PresenceType != PresenceType.Npc)
-                {
-                    // agent must not be a god
-                    if (presence.GodLevel >= 200) return;
-
-                    if (destination == String.Empty)
-                        destination = World.RegionInfo.RegionName;
-
-                    // agent must be over the owners land
-                    if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
-                    {
-                        DoLLTeleport(presence, destination, targetPos, targetLookAt);
-                    }
-                    else // or must be wearing the prim
-                    {
-                        if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
-                        {
-                            DoLLTeleport(presence, destination, targetPos, targetLookAt);
-                        }
-                    }
-                }
-            }
-        }
-
-        public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt)
-        {
-            m_host.AddScriptLPS(1);
-            UUID agentId = new UUID();
-
-            ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y);
-
-            if (UUID.TryParse(agent, out agentId))
-            {
-                ScenePresence presence = World.GetScenePresence(agentId);
-                if (presence != null && presence.PresenceType != PresenceType.Npc)
-                {
-                    // agent must not be a god
-                    if (presence.GodLevel >= 200) return;
-
-                    // agent must be over the owners land
-                    if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
-                    {
-                        World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
-                    }
-                    else // or must be wearing the prim
-                    {
-                        if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
-                        {
-                            World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
-                        }
-                    }
-                }
-            }
-        }
-
-        private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt)
-        {
-            UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination);
-
-            // The destinaion is not an asset ID and also doesn't name a landmark.
-            // Use it as a sim name
-            if (assetID == UUID.Zero)
-            {
-                World.RequestTeleportLocation(sp.ControllingClient, destination, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
-                return;
-            }
-
-            AssetBase lma = World.AssetService.Get(assetID.ToString());
-            if (lma == null)
-                return;
-
-            if (lma.Type != (sbyte)AssetType.Landmark)
-                return;
-
-            AssetLandmark lm = new AssetLandmark(lma);
-
-            World.RequestTeleportLocation(sp.ControllingClient, lm.RegionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
-        }
-
-        public void llTextBox(string agent, string message, int chatChannel)
-        {
-            IDialogModule dm = World.RequestModuleInterface();
-
-            if (dm == null)
-                return;
-
-            m_host.AddScriptLPS(1);
-            UUID av = new UUID();
-            if (!UUID.TryParse(agent,out av))
-            {
-                Error("llTextBox", "First parameter must be a key");
-                return;
-            }
-
-            if (message == string.Empty)
-            {
-                Error("llTextBox", "Empty message");
-            }
-            else if (message.Length > 512)
-            {
-                Error("llTextBox", "Message more than 512 characters");
-            }
-            else
-            {
-                dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
-                ScriptSleep(m_sleepMsOnTextBox);
-            }
-        }
-
-        public void llModifyLand(int action, int brush)
-        {
-            m_host.AddScriptLPS(1);
-            ITerrainModule tm = m_ScriptEngine.World.RequestModuleInterface();
-            if (tm != null)
-            {
-                tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID);
-            }
-        }
-
-        public void llCollisionSound(string impact_sound, double impact_volume)
-        {
-            m_host.AddScriptLPS(1);
-
-            // TODO: Parameter check logic required.
-            m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
-            m_host.CollisionSoundVolume = (float)impact_volume;
-        }
-
-        public LSL_String llGetAnimation(string id)
-        {
-            // This should only return a value if the avatar is in the same region
-            m_host.AddScriptLPS(1);
-            UUID avatar = (UUID)id;
-            ScenePresence presence = World.GetScenePresence(avatar);
-            if (presence == null)
-                return "";
-
-            if (m_host.RegionHandle == presence.RegionHandle)
-            {
-                Dictionary animationstateNames = DefaultAvatarAnimations.AnimStateNames;
-
-                if (presence != null)
-                {
-                    AnimationSet currentAnims = presence.Animator.Animations;
-                    string currentAnimationState = String.Empty;
-                    if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState))
-                        return currentAnimationState;
-                }
-            }
-
-            return String.Empty;
-        }
-
-        public void llMessageLinked(int linknumber, int num, string msg, string id)
-        {
-            m_host.AddScriptLPS(1);
-
-            List parts = GetLinkParts(linknumber);
-
-            UUID partItemID;
-            foreach (SceneObjectPart part in parts)
-            {
-                foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems())
-                {
-                    if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT)
-                    {
-                        partItemID = item.ItemID;
-                        int linkNumber = m_host.LinkNum;
-                        if (m_host.ParentGroup.PrimCount == 1)
-                            linkNumber = 0;
-
-                        object[] resobj = new object[]
-                                  {
-                                      new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
-                                  };
-
-                        m_ScriptEngine.PostScriptEvent(partItemID,
-                                new EventParams("link_message",
-                                resobj, new DetectParams[0]));
-                    }
-                }
-            }
-        }
-
-        public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
-        {
-            m_host.AddScriptLPS(1);
-            bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing;
-            bool pushAllowed = false;
-
-            bool pusheeIsAvatar = false;
-            UUID targetID = UUID.Zero;
-
-            if (!UUID.TryParse(target,out targetID))
-                return;
-
-            ScenePresence pusheeav = null;
-            Vector3 PusheePos = Vector3.Zero;
-            SceneObjectPart pusheeob = null;
-
-            ScenePresence avatar = World.GetScenePresence(targetID);
-            if (avatar != null)
-            {
-                pusheeIsAvatar = true;
-
-                // Pushee doesn't have a physics actor
-                if (avatar.PhysicsActor == null)
-                    return;
-
-                // Pushee is in GodMode this pushing object isn't owned by them
-                if (avatar.GodLevel > 0 && m_host.OwnerID != targetID)
-                    return;
-
-                pusheeav = avatar;
-
-                // Find pushee position
-                // Pushee Linked?
-                SceneObjectPart sitPart = pusheeav.ParentPart;
-                if (sitPart != null)
-                    PusheePos = sitPart.AbsolutePosition;
-                else
-                    PusheePos = pusheeav.AbsolutePosition;
-            }
-
-            if (!pusheeIsAvatar)
-            {
-                // not an avatar so push is not affected by parcel flags
-                pusheeob = World.GetSceneObjectPart((UUID)target);
-
-                // We can't find object
-                if (pusheeob == null)
-                    return;
-
-                // Object not pushable.  Not an attachment and has no physics component
-                if (!pusheeob.ParentGroup.IsAttachment && pusheeob.PhysActor == null)
-                    return;
-
-                PusheePos = pusheeob.AbsolutePosition;
-                pushAllowed = true;
-            }
-            else
-            {
-                if (pushrestricted)
-                {
-                    ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
-
-                    // We didn't find the parcel but region is push restricted so assume it is NOT ok
-                    if (targetlandObj == null)
-                        return;
-
-                    // Need provisions for Group Owned here
-                    if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
-                        targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID)
-                    {
-                        pushAllowed = true;
-                    }
-                }
-                else
-                {
-                    ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
-                    if (targetlandObj == null)
-                    {
-                        // We didn't find the parcel but region isn't push restricted so assume it's ok
-                        pushAllowed = true;
-                    }
-                    else
-                    {
-                        // Parcel push restriction
-                        if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject)
-                        {
-                            // Need provisions for Group Owned here
-                            if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
-                                targetlandObj.LandData.IsGroupOwned ||
-                                m_host.OwnerID == targetID)
-                            {
-                                pushAllowed = true;
-                            }
-
-                            //ParcelFlags.RestrictPushObject
-                            //pushAllowed = true;
-                        }
-                        else
-                        {
-                            // Parcel isn't push restricted
-                            pushAllowed = true;
-                        }
-                    }
-                }
-            }
-
-            if (pushAllowed)
-            {
-                float distance = (PusheePos - m_host.AbsolutePosition).Length();
-                float distance_term = distance * distance * distance; // Script Energy
-                float pusher_mass = m_host.GetMass();
-
-                float PUSH_ATTENUATION_DISTANCE = 17f;
-                float PUSH_ATTENUATION_SCALE = 5f;
-                float distance_attenuation = 1f;
-                if (distance > PUSH_ATTENUATION_DISTANCE)
-                {
-                    float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE;
-                    distance_attenuation = 1f / normalized_units;
-                }
-
-                Vector3 applied_linear_impulse = impulse;
-                {
-                    float impulse_length = applied_linear_impulse.Length();
-
-                    float desired_energy = impulse_length * pusher_mass;
-                    if (desired_energy > 0f)
-                        desired_energy += distance_term;
-
-                    float scaling_factor = 1f;
-                    scaling_factor *= distance_attenuation;
-                    applied_linear_impulse *= scaling_factor;
-
-                }
-
-                if (pusheeIsAvatar)
-                {
-                    if (pusheeav != null)
-                    {
-                        PhysicsActor pa = pusheeav.PhysicsActor;
-
-                        if (pa != null)
-                        {
-                            if (local != 0)
-                            {
-                                applied_linear_impulse *= m_host.GetWorldRotation();
-                            }
-
-                            pa.AddForce(applied_linear_impulse, true);
-                        }
-                    }
-                }
-                else
-                {
-                    if (pusheeob != null)
-                    {
-                        if (pusheeob.PhysActor != null)
-                        {
-                            pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
-                        }
-                    }
-                }
-            }
-        }
-
-        public void llPassCollisions(int pass)
-        {
-            m_host.AddScriptLPS(1);
-            if (pass == 0)
-            {
-                m_host.PassCollisions = false;
-            }
-            else
-            {
-                m_host.PassCollisions = true;
-            }
-        }
-
-        public LSL_String llGetScriptName()
-        {
-            m_host.AddScriptLPS(1);
-
-            return m_item.Name != null ? m_item.Name : String.Empty;
-        }
-
-        public LSL_Integer llGetLinkNumberOfSides(int link)
-        {
-            m_host.AddScriptLPS(1);
-
-            SceneObjectPart linkedPart;
-
-            if (link == ScriptBaseClass.LINK_ROOT)
-                linkedPart = m_host.ParentGroup.RootPart;
-            else if (link == ScriptBaseClass.LINK_THIS)
-                linkedPart = m_host;
-            else
-                linkedPart = m_host.ParentGroup.GetLinkNumPart(link);
-
-            return GetNumberOfSides(linkedPart);
-        }
-
-        public LSL_Integer llGetNumberOfSides()
-        {
-            m_host.AddScriptLPS(1);
-
-            return GetNumberOfSides(m_host);
-        }
-
-        protected int GetNumberOfSides(SceneObjectPart part)
-        {
-            int sides = part.GetNumberOfSides();
-
-            if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
-            {
-                // Make up for a bug where LSL shows 4 sides rather than 2
-                sides += 2;
-            }
-
-            return sides;
-        }
-
-
-        /* The new / changed functions were tested with the following LSL script:
-
-        default
-        {
-            state_entry()
-            {
-                rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
-
-                llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
-                llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
-
-                // convert back and forth between quaternion <-> vector and angle
-
-                rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
-
-                llOwnerSay("Old rotation was: "+(string) rot);
-                llOwnerSay("re-converted rotation is: "+(string) newrot);
-
-                llSetRot(rot);  // to check the parameters in the prim
-            }
-        }
-        */
-
-        // Xantor 29/apr/2008
-        // Returns rotation described by rotating angle radians about axis.
-        // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
-        public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
-        {
-            m_host.AddScriptLPS(1);
-
-            double x, y, z, s, t;
-
-            s = Math.Cos(angle * 0.5);
-            t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs
-            axis =  LSL_Vector.Norm(axis);
-            x = axis.x * t;
-            y = axis.y * t;
-            z = axis.z * t;
-
-            return new LSL_Rotation(x,y,z,s);
-        }
-
-        /// 
-        /// Returns the axis of rotation for a quaternion
-        /// 
-        /// 
-        /// 
-        public LSL_Vector llRot2Axis(LSL_Rotation rot)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (Math.Abs(rot.s) > 1) // normalization needed
-                rot.Normalize();
-
-            double s = Math.Sqrt(1 - rot.s * rot.s);
-            if (s < 0.001)
-            {
-                return new LSL_Vector(1, 0, 0);
-            }
-            else
-            {
-                double invS = 1.0 / s;
-                if (rot.s < 0) invS = -invS;
-                return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
-            }
-        }
-
-
-        // Returns the angle of a quaternion (see llRot2Axis for the axis)
-        public LSL_Float llRot2Angle(LSL_Rotation rot)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (Math.Abs(rot.s) > 1) // normalization needed
-                rot.Normalize();
-
-            double angle = 2 * Math.Acos(rot.s);
-            if (angle > Math.PI) 
-                angle = 2 * Math.PI - angle;
-
-            return angle;
-        }
-
-        public LSL_Float llAcos(double val)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Acos(val);
-        }
-
-        public LSL_Float llAsin(double val)
-        {
-            m_host.AddScriptLPS(1);
-            return (double)Math.Asin(val);
-        }
-
-        // jcochran 5/jan/2012
-        public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
-        {
-            m_host.AddScriptLPS(1);
-
-            double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s);
-            double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s);
-            double aa_bb = aa * bb;
-            if (aa_bb == 0) return 0.0;
-            double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s);
-            double quotient = (ab * ab) / aa_bb;
-            if (quotient >= 1.0) return 0.0;
-            return Math.Acos(2 * quotient - 1);
-        }
-
-        public LSL_String llGetInventoryKey(string name)
-        {
-            m_host.AddScriptLPS(1);
-
-            TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
-
-            if (item == null)
-                return UUID.Zero.ToString();
-
-            if ((item.CurrentPermissions
-                 & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
-                    == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
-            {
-                return item.AssetID.ToString();
-            }
-
-            return UUID.Zero.ToString();
-        }
-
-        public void llAllowInventoryDrop(int add)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (add != 0)
-                m_host.ParentGroup.RootPart.AllowedDrop = true;
-            else
-                m_host.ParentGroup.RootPart.AllowedDrop = false;
-
-            // Update the object flags
-            m_host.ParentGroup.RootPart.aggregateScriptEvents();
-        }
-
-        public LSL_Vector llGetSunDirection()
-        {
-            m_host.AddScriptLPS(1);
-
-            LSL_Vector SunDoubleVector3;
-            Vector3 SunFloatVector3;
-
-            // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule
-            // have to convert from Vector3 (float) to LSL_Vector (double)
-            SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
-            SunDoubleVector3.x = (double)SunFloatVector3.X;
-            SunDoubleVector3.y = (double)SunFloatVector3.Y;
-            SunDoubleVector3.z = (double)SunFloatVector3.Z;
-
-            return SunDoubleVector3;
-        }
-
-        public LSL_Vector llGetTextureOffset(int face)
-        {
-            m_host.AddScriptLPS(1);
-            return GetTextureOffset(m_host, face);
-        }
-
-        protected LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            LSL_Vector offset = new LSL_Vector();
-            if (face == ScriptBaseClass.ALL_SIDES)
-            {
-                face = 0;
-            }
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                offset.x = tex.GetFace((uint)face).OffsetU;
-                offset.y = tex.GetFace((uint)face).OffsetV;
-                offset.z = 0.0;
-                return offset;
-            }
-            else
-            {
-                return offset;
-            }
-        }
-
-        public LSL_Vector llGetTextureScale(int side)
-        {
-            m_host.AddScriptLPS(1);
-            Primitive.TextureEntry tex = m_host.Shape.Textures;
-            LSL_Vector scale;
-            if (side == -1)
-            {
-                side = 0;
-            }
-            scale.x = tex.GetFace((uint)side).RepeatU;
-            scale.y = tex.GetFace((uint)side).RepeatV;
-            scale.z = 0.0;
-            return scale;
-        }
-
-        public LSL_Float llGetTextureRot(int face)
-        {
-            m_host.AddScriptLPS(1);
-            return GetTextureRot(m_host, face);
-        }
-
-        protected LSL_Float GetTextureRot(SceneObjectPart part, int face)
-        {
-            Primitive.TextureEntry tex = part.Shape.Textures;
-            if (face == -1)
-            {
-                face = 0;
-            }
-            if (face >= 0 && face < GetNumberOfSides(part))
-            {
-                return tex.GetFace((uint)face).Rotation;
-            }
-            else
-            {
-                return 0.0;
-            }
-        }
-
-        public LSL_Integer llSubStringIndex(string source, string pattern)
-        {
-            m_host.AddScriptLPS(1);
-            return source.IndexOf(pattern);
-        }
-
-        public LSL_String llGetOwnerKey(string id)
-        {
-            m_host.AddScriptLPS(1);
-            UUID key = new UUID();
-            if (UUID.TryParse(id, out key))
-            {
-                try
-                {
-                    SceneObjectPart obj = World.GetSceneObjectPart(key);
-                    if (obj == null)
-                        return id; // the key is for an agent so just return the key
-                    else
-                        return obj.OwnerID.ToString();
-                }
-                catch (KeyNotFoundException)
-                {
-                    return id; // The Object/Agent not in the region so just return the key
-                }
-            }
-            else
-            {
-                return UUID.Zero.ToString();
-            }
-        }
-
-        public LSL_Vector llGetCenterOfMass()
-        {
-            m_host.AddScriptLPS(1);
-
-            return new LSL_Vector(m_host.GetCenterOfMass());
-        }
-
-        public LSL_List llListSort(LSL_List src, int stride, int ascending)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (stride <= 0)
-            {
-                stride = 1;
-            }
-            return src.Sort(stride, ascending);
-        }
-
-        public LSL_Integer llGetListLength(LSL_List src)
-        {
-            m_host.AddScriptLPS(1);
-
-            if (src == null)
-            {
-                return 0;
-            }
-            else
-            {
-                return src.Length;
-            }
-        }
-
-        public LSL_Integer llList2Integer(LSL_List src, int index)
-        {
-            m_host.AddScriptLPS(1);
-            if (index < 0)
-            {
-                index = src.Length + index;
-            }
-            if (index >= src.Length || index < 0)
-            {
-                return 0;
-            }
-
-            // Vectors & Rotations always return zero in SL, but
-            //  keys don't always return zero, it seems to be a bit complex.
-            else if (src.Data[index] is LSL_Vector ||
-                    src.Data[index] is LSL_Rotation)
-            {
-                return 0;
-            }
-            try
-            {
-
-                if (src.Data[index] is LSL_Integer)
-                    return (LSL_Integer)src.Data[index];
-                else if (src.Data[index] is LSL_Float)
-                    return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
-                return new LSL_Integer(src.Data[index].ToString());
-            }
-            catch (FormatException)
-            {
-                return 0;
-            }
-        }
-
-        public LSL_Float llList2Float(LSL_List src, int index)
-        {
-            m_host.AddScriptLPS(1);
-            if (index < 0)
-            {
-                index = src.Length + index;
-            }
-            if (index >= src.Length || index < 0)
-            {
-                return 0.0;
-            }
-
-            // Vectors & Rotations always return zero in SL
-            else if (src.Data[index] is LSL_Vector ||
-                    src.Data[index] is LSL_Rotation)
-            {
-                return 0;
-            }
-            // valid keys seem to get parsed as integers then converted to floats
-            else
-            {
-                UUID uuidt;
-                if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt))
-                {
-                    return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value);
-                }
-            }
-            try
-            {
-                if (src.Data[index] is LSL_Integer)
-                    return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
-                else if (src.Data[index] is LSL_Float)
-                    return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
-                else if (src.Data[index] is LSL_String)
-                    return Convert.ToDouble(((LSL_String)src.Data[index]).m_string);
-                return Convert.ToDouble(src.Data[index]);
-            }
-            catch (FormatException)
-            {
-                return 0.0;
-            }
-        }
-
-        public LSL_String llList2String(LSL_List src, int index)
-        {
-            m_host.AddScriptLPS(1);
-            if (index < 0)
-            {
-                index = src.Length + index;
-            }
-            if (index >= src.Length || index < 0)
-            {
-                return String.Empty;
-            }
-            return src.Data[index].ToString();
-        }
-
-        public LSL_Key llList2Key(LSL_List src, int index)
-        {
-            m_host.AddScriptLPS(1);
-            if (index < 0)
-            {
-                index = src.Length + index;
-            }
-
-            if (index >= src.Length || index < 0)
-            {
-                return "";
-            }
-
-            // SL spits out an empty string for types other than key & string
-            // At the time of patching, LSL_Key is currently LSL_String,
-            // so the OR check may be a little redundant, but it's being done
-            // for completion and should LSL_Key ever be implemented
-            // as it's own struct
-            // NOTE: 3rd case is needed because a NULL_KEY comes through as
-            // type 'obj' and wrongly returns ""
-            else if (!(src.Data[index] is LSL_String ||
-                       src.Data[index] is LSL_Key ||
-                       src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000"))
-            {
-                return "";
-            }
-
-            return src.Data[index].ToString();
-        }
-
-        public LSL_Vector llList2Vector(LSL_List src, int index)
-        {
-            m_host.AddScriptLPS(1);
-            if (index < 0)
-            {
-                index = src.Length + index;
-            }
-            if (index >= src.Length || index < 0)
-            {
-                return new LSL_Vector(0, 0, 0);
-            }
-            if (src.Data[index].GetType() == typeof(LSL_Vector))
-            {
-                return (LSL_Vector)src.Data[index];
-            }
-
-            // SL spits always out ZERO_VECTOR for anything other than
-            // strings or vectors. Although keys always return ZERO_VECTOR,
-            // it is currently difficult to make the distinction between
-            // a string, a key as string and a string that by coincidence
-            // is a string, so we're going to leave that up to the
-            // LSL_Vector constructor.
-            else if (!(src.Data[index] is LSL_String ||
-                    src.Data[index] is LSL_Vector))
-            {
-                return new LSL_Vector(0, 0, 0);
-            }
-            else
-            {
-                return new LSL_Vector(src.Data[index].ToString());
-            }
-        }
-
-        public LSL_Rotation llList2Rot(LSL_List src, int index)
-        {
-            m_host.AddScriptLPS(1);
-            if (index < 0)
-            {
-                index = src.Length + index;
-            }
-            if (index >= src.Length || index < 0)
-            {
-                return new LSL_Rotation(0, 0, 0, 1);
-            }
-
-            // SL spits always out ZERO_ROTATION for anything other than
-            // strings or vectors. Although keys always return ZERO_ROTATION,
-            // it is currently difficult to make the distinction between
-            // a string, a key as string and a string that by coincidence
-            // is a string, so we're going to leave that up to the
-            // LSL_Rotation constructor.
-            else if (!(src.Data[index] is LSL_String ||
-                    src.Data[index] is LSL_Rotation))
-            {
-                return new LSL_Rotation(0, 0, 0, 1);
-            }
-            else if (src.Data[index].GetType() == typeof(LSL_Rotation))
-            {
-                return (LSL_Rotation)src.Data[index];
-            }
-            else
-            {
-                return new LSL_Rotation(src.Data[index].ToString());
-            }
-        }
-
-        public LSL_List llList2List(LSL_List src, int start, int end)
-        {
-            m_host.AddScriptLPS(1);
-            return src.GetSublist(start, end);
-        }
-
-        public LSL_List llDeleteSubList(LSL_List src, int start, int end)
-        {
-            return src.DeleteSublist(start, end);
-        }
-
-        public LSL_Integer llGetListEntryType(LSL_List src, int index)
-        {
-            m_host.AddScriptLPS(1);
-            if (index < 0)
-            {
-                index = src.Length + index;
-            }
-            if (index >= src.Length)
-            {
-                return 0;
-            }
-
-            if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
-                return 1;
-            if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
-                return 2;
-            if (src.Data[index] is LSL_String || src.Data[index] is String)
-            {
-                UUID tuuid;
-                if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
-                {
-                    return 4;
-                }
-                else
-                {
-                    return 3;
-                }
-            }
-            if (src.Data[index] is LSL_Vector)
-                return 5;
-            if (src.Data[index] is LSL_Rotation)
-                return 6;
-            if (src.Data[index] is LSL_List)
-                return 7;
-            return 0;
-
-        }
-
-        /// 
-        /// Process the supplied list and return the
-        /// content of the list formatted as a comma
-        /// separated list. There is a space after
-        /// each comma.
-        /// 
-        public LSL_String llList2CSV(LSL_List src)
-        {
-            m_host.AddScriptLPS(1);
-
-            return string.Join(", ",
-                    (new List