PageRenderTime 61ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 3ms

/Aurora/AuroraDotNetEngine/APIs/LSL_Api.cs

https://bitbucket.org/VirtualReality/aurora-sim
C# | 11892 lines | 9029 code | 1744 blank | 1119 comment | 2752 complexity | 3e42528a41dc4612bd21e14c964eefd9 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the Aurora-Sim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Linq;
  31. using System.Runtime.Remoting.Lifetime;
  32. using System.Text;
  33. using System.Threading;
  34. using System.Text.RegularExpressions;
  35. using Nini.Config;
  36. using OpenMetaverse;
  37. using OpenMetaverse.Packets;
  38. using Aurora.Framework;
  39. using OpenSim.Region.Framework.Interfaces;
  40. using OpenSim.Region.Framework.Scenes;
  41. using OpenSim.Region.Framework.Scenes.Serialization;
  42. using Aurora.ScriptEngine.AuroraDotNetEngine.Plugins;
  43. using Aurora.ScriptEngine.AuroraDotNetEngine.APIs.Interfaces;
  44. using Aurora.ScriptEngine.AuroraDotNetEngine.Runtime;
  45. using OpenSim.Services.Interfaces;
  46. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  47. using PrimType = Aurora.Framework.PrimType;
  48. using AssetLandmark = Aurora.Framework.AssetLandmark;
  49. using LSL_Float = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLFloat;
  50. using LSL_Integer = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLInteger;
  51. using LSL_Key = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
  52. using LSL_List = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.list;
  53. using LSL_Rotation = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Quaternion;
  54. using LSL_String = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
  55. using LSL_Vector = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Vector3;
  56. namespace Aurora.ScriptEngine.AuroraDotNetEngine.APIs
  57. {
  58. /// <summary>
  59. /// Contains all LSL ll-functions. This class will be in Default AppDomain.
  60. /// </summary>
  61. [Serializable]
  62. public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
  63. {
  64. protected IScriptModulePlugin m_ScriptEngine;
  65. protected ISceneChildEntity m_host;
  66. protected uint m_localID;
  67. protected UUID m_itemID;
  68. protected bool throwErrorOnNotImplemented = true;
  69. protected float m_ScriptDelayFactor = 1.0f;
  70. protected float m_ScriptDistanceFactor = 1.0f;
  71. protected float m_MinTimerInterval = 0.1f;
  72. protected DateTime m_timer = DateTime.Now;
  73. protected bool m_waitingForScriptAnswer = false;
  74. protected bool m_automaticLinkPermission = false;
  75. protected IMessageTransferModule m_TransferModule = null;
  76. protected int m_notecardLineReadCharsMax = 255;
  77. protected int m_scriptConsoleChannel = 0;
  78. protected bool m_scriptConsoleChannelEnabled = false;
  79. protected IUrlModule m_UrlModule = null;
  80. internal ScriptProtectionModule ScriptProtection;
  81. protected IWorldComm m_comms = null;
  82. // MUST be a ref type
  83. public class UserInfoCacheEntry
  84. {
  85. public int time;
  86. public UserAccount account;
  87. public UserInfo pinfo;
  88. }
  89. protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
  90. new Dictionary<UUID, UserInfoCacheEntry>();
  91. public void Initialize(IScriptModulePlugin ScriptEngine, ISceneChildEntity host, uint localID, UUID itemID, ScriptProtectionModule module)
  92. {
  93. m_ScriptEngine = ScriptEngine;
  94. m_host = host;
  95. m_localID = localID;
  96. m_itemID = itemID;
  97. ScriptProtection = module;
  98. m_ScriptDelayFactor =
  99. m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
  100. m_ScriptDistanceFactor =
  101. m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
  102. m_MinTimerInterval =
  103. m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f);
  104. m_automaticLinkPermission =
  105. m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false);
  106. m_notecardLineReadCharsMax =
  107. m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
  108. if (m_notecardLineReadCharsMax > 65535)
  109. m_notecardLineReadCharsMax = 65535;
  110. m_TransferModule =
  111. World.RequestModuleInterface<IMessageTransferModule>();
  112. m_UrlModule = World.RequestModuleInterface<IUrlModule>();
  113. m_comms = World.RequestModuleInterface<IWorldComm>();
  114. }
  115. public IScriptApi Copy()
  116. {
  117. return new LSL_Api();
  118. }
  119. public string Name
  120. {
  121. get { return "ll"; }
  122. }
  123. public string InterfaceName
  124. {
  125. get { return "ILSL_Api"; }
  126. }
  127. /// <summary>
  128. /// We don't have to add any assemblies here
  129. /// </summary>
  130. public string[] ReferencedAssemblies
  131. {
  132. get { return new string[0]; }
  133. }
  134. /// <summary>
  135. /// We use the default namespace, so we don't have any to add
  136. /// </summary>
  137. public string[] NamespaceAdditions
  138. {
  139. get { return new string[0]; }
  140. }
  141. public void Dispose()
  142. {
  143. }
  144. public override Object InitializeLifetimeService()
  145. {
  146. ILease lease = (ILease)base.InitializeLifetimeService();
  147. if (lease != null && lease.CurrentState == LeaseState.Initial)
  148. {
  149. lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
  150. // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
  151. // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
  152. }
  153. return lease;
  154. }
  155. protected virtual void ScriptSleep(int delay)
  156. {
  157. delay = (int)(delay * m_ScriptDelayFactor);
  158. if (delay == 0)
  159. return;
  160. Thread.Sleep(delay);
  161. }
  162. /// <summary>
  163. /// This is the new sleep implementation that allows for us to not freeze the script thread while we run
  164. /// </summary>
  165. /// <param name="delay"></param>
  166. /// <returns></returns>
  167. protected DateTime PScriptSleep(int delay)
  168. {
  169. double dly = (delay * m_ScriptDelayFactor);
  170. if (dly == 0.0)
  171. return DateTime.Now;
  172. DateTime timeToStopSleeping = DateTime.Now.AddMilliseconds(dly);
  173. return timeToStopSleeping;
  174. }
  175. public IScene World
  176. {
  177. get { return m_host.ParentEntity.Scene; }
  178. }
  179. public void state(string newState)
  180. {
  181. m_ScriptEngine.SetState(m_itemID, newState);
  182. throw new EventAbortException();
  183. }
  184. /// <summary>
  185. /// Reset the named script. The script must be present
  186. /// in the same prim.
  187. /// </summary>
  188. public void llResetScript()
  189. {
  190. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  191. if (m_UrlModule != null)
  192. {
  193. m_UrlModule.ScriptRemoved(m_itemID);
  194. }
  195. m_ScriptEngine.ResetScript(m_host.UUID, m_itemID, true);
  196. }
  197. public void llResetOtherScript(string name)
  198. {
  199. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  200. UUID item;
  201. if ((item = ScriptByName(name)) != UUID.Zero)
  202. m_ScriptEngine.ResetScript(m_host.UUID, item, false);
  203. else
  204. ShoutError("llResetOtherScript: script " + name + " not found");
  205. }
  206. public LSL_Integer llGetScriptState(string name)
  207. {
  208. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  209. return new LSL_Integer();
  210. UUID item;
  211. if ((item = ScriptByName(name)) != UUID.Zero)
  212. {
  213. return m_ScriptEngine.GetScriptRunningState(item) ? 1 : 0;
  214. }
  215. ShoutError("llGetScriptState: script " + name + " not found");
  216. // If we didn't find it, then it's safe to
  217. // assume it is not running.
  218. return 0;
  219. }
  220. public LSL_Key llGenerateKey()
  221. {
  222. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Key();
  223. return UUID.Random().ToString();
  224. }
  225. public void llSetScriptState(string name, int run)
  226. {
  227. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  228. UUID item;
  229. // These functions are supposed to be robust,
  230. // so get the state one step at a time.
  231. if ((item = ScriptByName(name)) != UUID.Zero)
  232. {
  233. m_ScriptEngine.SetScriptRunningState(item, run == 1);
  234. }
  235. else
  236. {
  237. ShoutError("llSetScriptState: script " + name + " not found");
  238. }
  239. }
  240. public List<ISceneChildEntity> GetLinkParts(int linkType)
  241. {
  242. List<ISceneChildEntity> ret = new List<ISceneChildEntity> { m_host };
  243. if (linkType == ScriptBaseClass.LINK_SET)
  244. {
  245. if (m_host.ParentEntity != null)
  246. return new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  247. return ret;
  248. }
  249. if (linkType == ScriptBaseClass.LINK_ROOT)
  250. {
  251. if (m_host.ParentEntity != null)
  252. {
  253. ret = new List<ISceneChildEntity> { m_host.ParentEntity.RootChild };
  254. return ret;
  255. }
  256. return ret;
  257. }
  258. if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
  259. {
  260. if (m_host.ParentEntity == null)
  261. return new List<ISceneChildEntity>();
  262. ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  263. if (ret.Contains(m_host))
  264. ret.Remove(m_host);
  265. return ret;
  266. }
  267. if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
  268. {
  269. if (m_host.ParentEntity == null)
  270. return new List<ISceneChildEntity>();
  271. ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  272. if (ret.Contains(m_host.ParentEntity.RootChild))
  273. ret.Remove(m_host.ParentEntity.RootChild);
  274. return ret;
  275. }
  276. if (linkType == ScriptBaseClass.LINK_THIS)
  277. {
  278. return ret;
  279. }
  280. if (linkType < 0 || m_host.ParentEntity == null)
  281. return new List<ISceneChildEntity>();
  282. IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
  283. if (target is ISceneChildEntity)
  284. {
  285. ret = new List<ISceneChildEntity> { target as ISceneChildEntity };
  286. }
  287. //No allowing scene presences to be found here
  288. return ret;
  289. }
  290. public List<IEntity> GetLinkPartsAndEntities(int linkType)
  291. {
  292. List<IEntity> ret = new List<IEntity> { m_host };
  293. if (linkType == ScriptBaseClass.LINK_SET)
  294. {
  295. if (m_host.ParentEntity != null)
  296. {
  297. List<ISceneChildEntity> parts = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  298. #if (!ISWIN)
  299. return parts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  300. {
  301. return (IEntity)part;
  302. }));
  303. #else
  304. return parts.ConvertAll (part => (IEntity) part);
  305. #endif
  306. }
  307. return ret;
  308. }
  309. if (linkType == ScriptBaseClass.LINK_ROOT)
  310. {
  311. if (m_host.ParentEntity != null)
  312. {
  313. ret = new List<IEntity> { m_host.ParentEntity.RootChild };
  314. return ret;
  315. }
  316. return ret;
  317. }
  318. if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
  319. {
  320. if (m_host.ParentEntity == null)
  321. return new List<IEntity>();
  322. List<ISceneChildEntity> sceneobjectparts = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  323. #if (!ISWIN)
  324. ret = sceneobjectparts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  325. {
  326. return (IEntity)part;
  327. }));
  328. #else
  329. ret = sceneobjectparts.ConvertAll (part => (IEntity) part);
  330. #endif
  331. if (ret.Contains(m_host))
  332. ret.Remove(m_host);
  333. return ret;
  334. }
  335. if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
  336. {
  337. if (m_host.ParentEntity == null)
  338. return new List<IEntity>();
  339. List<ISceneChildEntity> children = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  340. #if (!ISWIN)
  341. ret = children.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  342. {
  343. return (IEntity)part;
  344. }));
  345. #else
  346. ret = children.ConvertAll (part => (IEntity) part);
  347. #endif
  348. if (ret.Contains(m_host.ParentEntity.RootChild))
  349. ret.Remove(m_host.ParentEntity.RootChild);
  350. return ret;
  351. }
  352. if (linkType == ScriptBaseClass.LINK_THIS)
  353. {
  354. return ret;
  355. }
  356. if (linkType < 0 || m_host.ParentEntity == null)
  357. return new List<IEntity>();
  358. IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
  359. if (target == null)
  360. return new List<IEntity>();
  361. ret = new List<IEntity> { target };
  362. return ret;
  363. }
  364. protected UUID InventorySelf()
  365. {
  366. UUID invItemID = new UUID();
  367. lock (m_host.TaskInventory)
  368. {
  369. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  370. {
  371. if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
  372. {
  373. invItemID = inv.Key;
  374. break;
  375. }
  376. }
  377. }
  378. return invItemID;
  379. }
  380. protected UUID InventoryKey(string name, int type)
  381. {
  382. lock (m_host.TaskInventory)
  383. {
  384. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  385. {
  386. if (inv.Value.Name == name)
  387. {
  388. if (inv.Value.Type != type)
  389. return UUID.Zero;
  390. return inv.Value.AssetID;
  391. }
  392. }
  393. }
  394. return UUID.Zero;
  395. }
  396. protected UUID InventoryKey(string name, bool throwExceptionIfDoesNotExist)
  397. {
  398. lock (m_host.TaskInventory)
  399. {
  400. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  401. {
  402. if (inv.Value.Name == name)
  403. {
  404. return inv.Value.AssetID;
  405. }
  406. }
  407. }
  408. if (throwExceptionIfDoesNotExist)
  409. {
  410. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  411. if (chatModule != null)
  412. chatModule.SimChat("Could not find sound '" + name + "'.",
  413. ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
  414. m_host.Name, m_host.UUID, false, World);
  415. }
  416. return UUID.Zero;
  417. }
  418. /// <summary>
  419. /// accepts a valid UUID, -or- a name of an inventory item.
  420. /// Returns a valid UUID or UUID.Zero if key invalid and item not found
  421. /// in prim inventory.
  422. /// </summary>
  423. /// <param name="k"></param>
  424. /// <param name="throwExceptionIfDoesNotExist"></param>
  425. /// <returns></returns>
  426. protected UUID KeyOrName(string k, bool throwExceptionIfDoesNotExist)
  427. {
  428. UUID key = UUID.Zero;
  429. // if we can parse the string as a key, use it.
  430. if (UUID.TryParse(k, out key))
  431. {
  432. return key;
  433. }
  434. // else try to locate the name in inventory of object. found returns key,
  435. // not found returns UUID.Zero which will translate to the default particle texture
  436. return InventoryKey(k, throwExceptionIfDoesNotExist);
  437. }
  438. // convert a LSL_Rotation to a Quaternion
  439. protected Quaternion Rot2Quaternion(LSL_Rotation r)
  440. {
  441. Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
  442. q.Normalize();
  443. return q;
  444. }
  445. //These are the implementations of the various ll-functions used by the LSL scripts.
  446. public LSL_Float llSin(double f)
  447. {
  448. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  449. return Math.Sin(f);
  450. }
  451. public LSL_Float llCos(double f)
  452. {
  453. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  454. return Math.Cos(f);
  455. }
  456. public LSL_Float llTan(double f)
  457. {
  458. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  459. return Math.Tan(f);
  460. }
  461. public LSL_Float llAtan2(double x, double y)
  462. {
  463. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  464. return Math.Atan2(x, y);
  465. }
  466. public LSL_Float llSqrt(double f)
  467. {
  468. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  469. return Math.Sqrt(f);
  470. }
  471. public LSL_Float llPow(double fbase, double fexponent)
  472. {
  473. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  474. return Math.Pow(fbase, fexponent);
  475. }
  476. public LSL_Integer llAbs(int i)
  477. {
  478. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  479. // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
  480. if (i == Int32.MinValue)
  481. return i;
  482. return Math.Abs(i);
  483. }
  484. public LSL_Float llFabs(double f)
  485. {
  486. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  487. return Math.Abs(f);
  488. }
  489. public LSL_Float llFrand(double mag)
  490. {
  491. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  492. lock (Util.RandomClass)
  493. {
  494. return Util.RandomClass.NextDouble() * mag;
  495. }
  496. }
  497. public LSL_Integer llFloor(double f)
  498. {
  499. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  500. return (int)Math.Floor(f);
  501. }
  502. public LSL_Integer llCeil(double f)
  503. {
  504. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  505. return (int)Math.Ceiling(f);
  506. }
  507. // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
  508. public LSL_Integer llRound(double f)
  509. {
  510. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  511. double RoundedNumber = Math.Round(f, MidpointRounding.AwayFromZero);
  512. //Attempt to fix rounded numbers like -4.5 arounding away from zero
  513. if (f < 0)
  514. {
  515. if (f + 0.5 == RoundedNumber || f - 0.5 == RoundedNumber)
  516. {
  517. RoundedNumber += 1;
  518. }
  519. }
  520. return (int)RoundedNumber;
  521. }
  522. //This next group are vector operations involving squaring and square root. ckrinke
  523. public LSL_Float llVecMag(LSL_Vector v)
  524. {
  525. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  526. return LSL_Vector.Mag(v);
  527. }
  528. public LSL_Vector llVecNorm(LSL_Vector v)
  529. {
  530. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  531. return LSL_Vector.Norm(v);
  532. }
  533. public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
  534. {
  535. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  536. double dx = a.x - b.x;
  537. double dy = a.y - b.y;
  538. double dz = a.z - b.z;
  539. return Math.Sqrt(dx * dx + dy * dy + dz * dz);
  540. }
  541. //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
  542. // Old implementation of llRot2Euler. Normalization not required as Atan2 function will
  543. // only return values >= -PI (-180 degrees) and <= PI (180 degrees).
  544. public LSL_Vector llRot2Euler(LSL_Rotation r)
  545. {
  546. //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
  547. LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
  548. double m = (t.x + t.y + t.z + t.s);
  549. if (m == 0) return new LSL_Vector();
  550. double n = 2 * (r.y * r.s + r.x * r.z);
  551. double p = m * m - n * n;
  552. if (p > 0)
  553. return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)),
  554. Math.Atan2(n, Math.Sqrt(p)),
  555. Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)));
  556. if (n > 0)
  557. return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z));
  558. return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z));
  559. }
  560. /* From wiki:
  561. The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
  562. in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
  563. a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
  564. vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
  565. */
  566. /* How we arrived at this llEuler2Rot
  567. *
  568. * Experiment in SL to determine conventions:
  569. * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
  570. * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
  571. * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
  572. *
  573. * Important facts about Quaternions
  574. * - multiplication is non-commutative (a*b != b*a)
  575. * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
  576. *
  577. * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
  578. * Qx = c1+i*s1
  579. * Qy = c2+j*s2;
  580. * Qz = c3+k*s3;
  581. *
  582. * Rotations applied in order (from above) Z, Y, X
  583. * Q = (Qz * Qy) * Qx
  584. * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
  585. * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
  586. * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
  587. * 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
  588. * 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
  589. * regroup: x=i*(s1*c2*c3+c1*s2*s3)
  590. * y=j*(c1*s2*c3-s1*c2*s3)
  591. * z=k*(s1*s2*c3+c1*c2*s3)
  592. * s= c1*c2*c3-s1*s2*s3
  593. *
  594. * This implementation agrees with the functions found here:
  595. * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
  596. * And with the results in SL.
  597. *
  598. * It's also possible to calculate llEuler2Rot by direct multiplication of
  599. * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
  600. * from the wiki).
  601. * Apparently in some cases this is better from a numerical precision perspective?
  602. */
  603. public LSL_Rotation llEuler2Rot(LSL_Vector v)
  604. {
  605. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  606. double c1 = Math.Cos(v.x * 0.5);
  607. double c2 = Math.Cos(v.y * 0.5);
  608. double c3 = Math.Cos(v.z * 0.5);
  609. double s1 = Math.Sin(v.x * 0.5);
  610. double s2 = Math.Sin(v.y * 0.5);
  611. double s3 = Math.Sin(v.z * 0.5);
  612. double x = s1 * c2 * c3 + c1 * s2 * s3;
  613. double y = c1 * s2 * c3 - s1 * c2 * s3;
  614. double z = s1 * s2 * c3 + c1 * c2 * s3;
  615. double s = c1 * c2 * c3 - s1 * s2 * s3;
  616. return new LSL_Rotation(x, y, z, s);
  617. }
  618. public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
  619. {
  620. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  621. double s;
  622. double tr = fwd.x + left.y + up.z + 1.0;
  623. if (tr >= 1.0)
  624. {
  625. s = 0.5 / Math.Sqrt(tr);
  626. return new LSL_Rotation(
  627. (left.z - up.y) * s,
  628. (up.x - fwd.z) * s,
  629. (fwd.y - left.x) * s,
  630. 0.25 / s);
  631. }
  632. double max = (left.y > up.z) ? left.y : up.z;
  633. if (max < fwd.x)
  634. {
  635. s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
  636. double x = s * 0.5;
  637. s = 0.5 / s;
  638. return new LSL_Rotation(
  639. x,
  640. (fwd.y + left.x) * s,
  641. (up.x + fwd.z) * s,
  642. (left.z - up.y) * s);
  643. }
  644. if (max == left.y)
  645. {
  646. s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
  647. double y = s * 0.5;
  648. s = 0.5 / s;
  649. return new LSL_Rotation(
  650. (fwd.y + left.x) * s,
  651. y,
  652. (left.z + up.y) * s,
  653. (up.x - fwd.z) * s);
  654. }
  655. s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
  656. double z = s * 0.5;
  657. s = 0.5 / s;
  658. return new LSL_Rotation(
  659. (up.x + fwd.z) * s,
  660. (left.z + up.y) * s,
  661. z,
  662. (fwd.y - left.x) * s);
  663. }
  664. public LSL_Vector llRot2Fwd(LSL_Rotation r)
  665. {
  666. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  667. return new LSL_Vector();
  668. double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  669. // m is always greater than zero
  670. // if m is not equal to 1 then Rotation needs to be normalized
  671. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  672. {
  673. m = 1.0 / Math.Sqrt(m);
  674. r.x *= m;
  675. r.y *= m;
  676. r.z *= m;
  677. r.s *= m;
  678. }
  679. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  680. double x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
  681. double y = 2 * (r.x * r.y + r.z * r.s);
  682. double z = 2 * (r.x * r.z - r.y * r.s);
  683. return (new LSL_Vector(x, y, z));
  684. }
  685. public LSL_Vector llRot2Left(LSL_Rotation r)
  686. {
  687. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  688. double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  689. // m is always greater than zero
  690. // if m is not equal to 1 then Rotation needs to be normalized
  691. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  692. {
  693. m = 1.0 / Math.Sqrt(m);
  694. r.x *= m;
  695. r.y *= m;
  696. r.z *= m;
  697. r.s *= m;
  698. }
  699. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  700. double x = 2 * (r.x * r.y - r.z * r.s);
  701. double y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
  702. double z = 2 * (r.x * r.s + r.y * r.z);
  703. return (new LSL_Vector(x, y, z));
  704. }
  705. public LSL_Vector llRot2Up(LSL_Rotation r)
  706. {
  707. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  708. double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  709. // m is always greater than zero
  710. // if m is not equal to 1 then Rotation needs to be normalized
  711. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  712. {
  713. m = 1.0 / Math.Sqrt(m);
  714. r.x *= m;
  715. r.y *= m;
  716. r.z *= m;
  717. r.s *= m;
  718. }
  719. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  720. double x = 2 * (r.x * r.z + r.y * r.s);
  721. double y = 2 * (-r.x * r.s + r.y * r.z);
  722. double z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
  723. return (new LSL_Vector(x, y, z));
  724. }
  725. public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
  726. {
  727. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  728. //A and B should both be normalized
  729. LSL_Rotation rotBetween;
  730. // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
  731. // continue calculation.
  732. if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
  733. {
  734. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  735. }
  736. else
  737. {
  738. a = LSL_Vector.Norm(a);
  739. b = LSL_Vector.Norm(b);
  740. double dotProduct = LSL_Vector.Dot(a, b);
  741. // There are two degenerate cases possible. These are for vectors 180 or
  742. // 0 degrees apart. These have to be detected and handled individually.
  743. //
  744. // Check for vectors 180 degrees apart.
  745. // A dot product of -1 would mean the angle between vectors is 180 degrees.
  746. if (dotProduct < -0.9999999f)
  747. {
  748. // First assume X axis is orthogonal to the vectors.
  749. LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
  750. orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
  751. // Check for near zero vector. A very small non-zero number here will create
  752. // a rotation in an undesired direction.
  753. rotBetween = LSL_Vector.Mag(orthoVector) > 0.0001 ? new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f) : new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
  754. }
  755. // Check for parallel vectors.
  756. // A dot product of 1 would mean the angle between vectors is 0 degrees.
  757. else if (dotProduct > 0.9999999f)
  758. {
  759. // Set zero rotation.
  760. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  761. }
  762. else
  763. {
  764. // All special checks have been performed so get the axis of rotation.
  765. LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
  766. // Quarternion s value is the length of the unit vector + dot product.
  767. double qs = 1.0 + dotProduct;
  768. rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
  769. // Normalize the rotation.
  770. double mag = LSL_Rotation.Mag(rotBetween);
  771. // We shouldn't have to worry about a divide by zero here. The qs value will be
  772. // non-zero because we already know if we're here, then the dotProduct is not -1 so
  773. // qs will not be zero. Also, we've already handled the input vectors being zero so the
  774. // crossProduct vector should also not be zero.
  775. rotBetween.x = rotBetween.x / mag;
  776. rotBetween.y = rotBetween.y / mag;
  777. rotBetween.z = rotBetween.z / mag;
  778. rotBetween.s = rotBetween.s / mag;
  779. // Check for undefined values and set zero rotation if any found. This code might not actually be required
  780. // any longer since zero vectors are checked for at the top.
  781. if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
  782. {
  783. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  784. }
  785. }
  786. }
  787. return rotBetween;
  788. }
  789. public void llWhisper(int channelID, string text)
  790. {
  791. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  792. if (text.Length > 1023)
  793. text = text.Substring(0, 1023);
  794. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  795. if (chatModule != null)
  796. chatModule.SimChat(text, ChatTypeEnum.Whisper, channelID,
  797. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
  798. if (m_comms != null)
  799. m_comms.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
  800. }
  801. public void llSay(int channelID, object m_text)
  802. {
  803. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  804. string text = m_text.ToString();
  805. if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
  806. {
  807. Console.WriteLine(text);
  808. }
  809. else
  810. {
  811. if (text.Length > 1023)
  812. text = text.Substring(0, 1023);
  813. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  814. if (chatModule != null)
  815. chatModule.SimChat(text, ChatTypeEnum.Say, channelID,
  816. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
  817. if (m_comms != null)
  818. m_comms.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
  819. }
  820. }
  821. public void llShout(int channelID, string text)
  822. {
  823. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  824. if (text.Length > 1023)
  825. text = text.Substring(0, 1023);
  826. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  827. if (chatModule != null)
  828. chatModule.SimChat(text, ChatTypeEnum.Shout, channelID,
  829. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, true, World);
  830. if (m_comms != null)
  831. m_comms.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
  832. }
  833. public void llRegionSay(int channelID, string text)
  834. {
  835. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  836. if (text.Length > 1023)
  837. text = text.Substring(0, 1023);
  838. if (channelID == 0) //0 isn't normally allowed, so check against a higher threat level
  839. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Moderate, "LSL", m_host, "LSL", m_itemID)) return;
  840. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  841. if (chatModule != null)
  842. chatModule.SimChat(text, ChatTypeEnum.Region, channelID,
  843. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
  844. if (m_comms != null)
  845. m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
  846. }
  847. public void llRegionSayTo(LSL_Key toID, int channelID, string text)
  848. {
  849. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  850. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  851. if (text.Length > 1023)
  852. text = text.Substring(0, 1023);
  853. if (channelID == 0)
  854. {
  855. IScenePresence presence = World.GetScenePresence(UUID.Parse(toID.m_string));
  856. if (presence != null)
  857. {
  858. if (chatModule != null)
  859. chatModule.TrySendChatMessage(presence, m_host.AbsolutePosition, m_host.AbsolutePosition,
  860. m_host.UUID, m_host.Name, ChatTypeEnum.Say, text, ChatSourceType.Object, 10000);
  861. }
  862. }
  863. if (m_comms != null)
  864. m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, UUID.Parse(toID.m_string), text);
  865. }
  866. public LSL_Integer llListen(int channelID, string name, string ID, string msg)
  867. {
  868. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  869. UUID keyID;
  870. UUID.TryParse(ID, out keyID);
  871. if (m_comms != null)
  872. return m_comms.Listen(m_itemID, m_host.UUID, channelID, name, keyID, msg);
  873. return -1;
  874. }
  875. public void llListenControl(int number, int active)
  876. {
  877. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  878. if (m_comms != null)
  879. m_comms.ListenControl(m_itemID, number, active);
  880. }
  881. public void llListenRemove(int number)
  882. {
  883. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  884. if (m_comms != null)
  885. m_comms.ListenRemove(m_itemID, number);
  886. }
  887. public void llSensor(string name, string id, int type, double range, double arc)
  888. {
  889. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  890. UUID keyID = UUID.Zero;
  891. UUID.TryParse(id, out keyID);
  892. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  893. sensorPlugin.SenseOnce(m_host.UUID, m_itemID, name, keyID, type, range, arc, m_host);
  894. }
  895. public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
  896. {
  897. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  898. UUID keyID = UUID.Zero;
  899. UUID.TryParse(id, out keyID);
  900. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  901. sensorPlugin.SetSenseRepeatEvent(m_host.UUID, m_itemID, name, keyID, type, range, arc, rate, m_host);
  902. }
  903. public void llSensorRemove()
  904. {
  905. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  906. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  907. sensorPlugin.RemoveScript(m_host.UUID, m_itemID);
  908. }
  909. public string resolveName(UUID objecUUID)
  910. {
  911. // try avatar username surname
  912. UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.AllScopeIDs, objecUUID);
  913. if (account != null)
  914. return account.Name;
  915. // try an scene object
  916. ISceneChildEntity SOP = World.GetSceneObjectPart(objecUUID);
  917. if (SOP != null)
  918. return SOP.Name;
  919. IEntity SensedObject;
  920. if (!World.Entities.TryGetValue(objecUUID, out SensedObject))
  921. {
  922. IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
  923. if (groups != null)
  924. {
  925. GroupRecord gr = groups.GetGroupRecord(objecUUID);
  926. if (gr != null)
  927. return gr.GroupName;
  928. }
  929. return String.Empty;
  930. }
  931. return SensedObject.Name;
  932. }
  933. public LSL_String llDetectedName(int number)
  934. {
  935. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  936. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  937. if (detectedParams == null)
  938. return String.Empty;
  939. return detectedParams.Name;
  940. }
  941. public LSL_String llDetectedKey(int number)
  942. {
  943. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  944. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  945. if (detectedParams == null)
  946. return String.Empty;
  947. return detectedParams.Key.ToString();
  948. }
  949. public LSL_String llDetectedOwner(int number)
  950. {
  951. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  952. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  953. if (detectedParams == null)
  954. return String.Empty;
  955. return detectedParams.Owner.ToString();
  956. }
  957. public LSL_Integer llDetectedType(int number)
  958. {
  959. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  960. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  961. if (detectedParams == null)
  962. return 0;
  963. return new LSL_Integer(detectedParams.Type);
  964. }
  965. public LSL_Vector llDetectedPos(int number)
  966. {
  967. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  968. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  969. if (detectedParams == null)
  970. return new LSL_Vector();
  971. return detectedParams.Position;
  972. }
  973. public LSL_Vector llDetectedVel(int number)
  974. {
  975. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  976. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  977. if (detectedParams == null)
  978. return new LSL_Vector();
  979. return detectedParams.Velocity;
  980. }
  981. public LSL_Vector llDetectedGrab(int number)
  982. {
  983. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  984. DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  985. if (parms == null)
  986. return new LSL_Vector(0, 0, 0);
  987. return parms.OffsetPos;
  988. }
  989. public LSL_Rotation llDetectedRot(int number)
  990. {
  991. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  992. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  993. if (detectedParams == null)
  994. return new LSL_Rotation();
  995. return detectedParams.Rotation;
  996. }
  997. public LSL_Integer llDetectedGroup(int number)
  998. {
  999. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  1000. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1001. if (detectedParams == null)
  1002. return new LSL_Integer(0);
  1003. if (m_host.GroupID == detectedParams.Group)
  1004. return new LSL_Integer(1);
  1005. return new LSL_Integer(0);
  1006. }
  1007. public LSL_Integer llDetectedLinkNumber(int number)
  1008. {
  1009. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  1010. DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1011. if (parms == null)
  1012. return new LSL_Integer(0);
  1013. return new LSL_Integer(parms.LinkNum);
  1014. }
  1015. /// <summary>
  1016. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
  1017. /// </summary>
  1018. public LSL_Vector llDetectedTouchBinormal(int index)
  1019. {
  1020. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1021. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1022. if (detectedParams == null)
  1023. return new LSL_Vector();
  1024. return detectedParams.TouchBinormal;

Large files files are truncated, but you can click here to view the full file