PageRenderTime 81ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 2ms

/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs

https://bitbucket.org/KyanhaLLC/opensim
C# | 11784 lines | 8932 code | 1681 blank | 1171 comment | 1937 complexity | cd8c1e05459df14cd225b18da69481df MD5 | raw file
Possible License(s): Unlicense, MIT, BSD-3-Clause

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

  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.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 OpenSimulator 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.Runtime.Remoting.Lifetime;
  31. using System.Text;
  32. using System.Threading;
  33. using System.Text.RegularExpressions;
  34. using Nini.Config;
  35. using log4net;
  36. using OpenMetaverse;
  37. using OpenMetaverse.Packets;
  38. using OpenSim;
  39. using OpenSim.Framework;
  40. using OpenSim.Region.CoreModules;
  41. using OpenSim.Region.CoreModules.World.Land;
  42. using OpenSim.Region.CoreModules.World.Terrain;
  43. using OpenSim.Region.Framework.Interfaces;
  44. using OpenSim.Region.Framework.Scenes;
  45. using OpenSim.Region.Framework.Scenes.Animation;
  46. using OpenSim.Region.Framework.Scenes.Scripting;
  47. using OpenSim.Region.Physics.Manager;
  48. using OpenSim.Region.ScriptEngine.Shared;
  49. using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
  50. using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
  51. using OpenSim.Region.ScriptEngine.Interfaces;
  52. using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
  53. using OpenSim.Services.Interfaces;
  54. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  55. using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
  56. using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
  57. using AssetLandmark = OpenSim.Framework.AssetLandmark;
  58. using RegionFlags = OpenSim.Framework.RegionFlags;
  59. using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
  60. using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
  61. using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  62. using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
  63. using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
  64. using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  65. using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
  66. using System.Reflection;
  67. namespace OpenSim.Region.ScriptEngine.Shared.Api
  68. {
  69. // MUST be a ref type
  70. public class UserInfoCacheEntry
  71. {
  72. public int time;
  73. public UserAccount account;
  74. public PresenceInfo pinfo;
  75. }
  76. /// <summary>
  77. /// Contains all LSL ll-functions. This class will be in Default AppDomain.
  78. /// </summary>
  79. public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
  80. {
  81. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  82. protected IScriptEngine m_ScriptEngine;
  83. protected SceneObjectPart m_host;
  84. /// <summary>
  85. /// Used for script sleeps when we are using co-operative script termination.
  86. /// </summary>
  87. /// <remarks>null if co-operative script termination is not active</remarks>
  88. WaitHandle m_coopSleepHandle;
  89. /// <summary>
  90. /// The item that hosts this script
  91. /// </summary>
  92. protected TaskInventoryItem m_item;
  93. protected bool throwErrorOnNotImplemented = true;
  94. protected AsyncCommandManager AsyncCommands = null;
  95. protected float m_ScriptDelayFactor = 1.0f;
  96. protected float m_ScriptDistanceFactor = 1.0f;
  97. protected float m_MinTimerInterval = 0.5f;
  98. protected float m_recoilScaleFactor = 0.0f;
  99. protected DateTime m_timer = DateTime.Now;
  100. protected bool m_waitingForScriptAnswer = false;
  101. protected bool m_automaticLinkPermission = false;
  102. protected IMessageTransferModule m_TransferModule = null;
  103. protected int m_notecardLineReadCharsMax = 255;
  104. protected int m_scriptConsoleChannel = 0;
  105. protected bool m_scriptConsoleChannelEnabled = false;
  106. protected IUrlModule m_UrlModule = null;
  107. protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
  108. protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
  109. protected ISoundModule m_SoundModule = null;
  110. public void Initialize(
  111. IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
  112. {
  113. m_ScriptEngine = scriptEngine;
  114. m_host = host;
  115. m_item = item;
  116. m_coopSleepHandle = coopSleepHandle;
  117. LoadConfig();
  118. m_TransferModule =
  119. m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
  120. m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
  121. m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
  122. AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
  123. }
  124. /// <summary>
  125. /// Load configuration items that affect script, object and run-time behavior. */
  126. /// </summary>
  127. private void LoadConfig()
  128. {
  129. m_ScriptDelayFactor =
  130. m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
  131. m_ScriptDistanceFactor =
  132. m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
  133. m_MinTimerInterval =
  134. m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f);
  135. m_automaticLinkPermission =
  136. m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false);
  137. m_notecardLineReadCharsMax =
  138. m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
  139. if (m_notecardLineReadCharsMax > 65535)
  140. m_notecardLineReadCharsMax = 65535;
  141. // load limits for particular subsystems.
  142. IConfig SMTPConfig;
  143. if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) {
  144. // there's an smtp config, so load in the snooze time.
  145. EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
  146. }
  147. // Rezzing an object with a velocity can create recoil. This feature seems to have been
  148. // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
  149. // it by this factor. May be zero to turn off recoil all together.
  150. m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
  151. }
  152. public override Object InitializeLifetimeService()
  153. {
  154. ILease lease = (ILease)base.InitializeLifetimeService();
  155. if (lease.CurrentState == LeaseState.Initial)
  156. {
  157. lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
  158. // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
  159. // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
  160. }
  161. return lease;
  162. }
  163. protected virtual void ScriptSleep(int delay)
  164. {
  165. delay = (int)((float)delay * m_ScriptDelayFactor);
  166. if (delay == 0)
  167. return;
  168. Sleep(delay);
  169. }
  170. protected virtual void Sleep(int delay)
  171. {
  172. if (m_coopSleepHandle == null)
  173. System.Threading.Thread.Sleep(delay);
  174. else
  175. CheckForCoopTermination(delay);
  176. }
  177. /// <summary>
  178. /// Check for co-operative termination.
  179. /// </summary>
  180. /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param>
  181. protected virtual void CheckForCoopTermination(int delay)
  182. {
  183. if (m_coopSleepHandle.WaitOne(delay))
  184. throw new ScriptCoopStopException();
  185. }
  186. public Scene World
  187. {
  188. get { return m_ScriptEngine.World; }
  189. }
  190. public void state(string newState)
  191. {
  192. m_ScriptEngine.SetState(m_item.ItemID, newState);
  193. }
  194. /// <summary>
  195. /// Reset the named script. The script must be present
  196. /// in the same prim.
  197. /// </summary>
  198. public void llResetScript()
  199. {
  200. m_host.AddScriptLPS(1);
  201. // We need to tell the URL module, if we hav one, to release
  202. // the allocated URLs
  203. if (m_UrlModule != null)
  204. m_UrlModule.ScriptRemoved(m_item.ItemID);
  205. m_ScriptEngine.ApiResetScript(m_item.ItemID);
  206. }
  207. public void llResetOtherScript(string name)
  208. {
  209. UUID item;
  210. m_host.AddScriptLPS(1);
  211. if ((item = GetScriptByName(name)) != UUID.Zero)
  212. m_ScriptEngine.ResetScript(item);
  213. else
  214. ShoutError("llResetOtherScript: script "+name+" not found");
  215. }
  216. public LSL_Integer llGetScriptState(string name)
  217. {
  218. UUID item;
  219. m_host.AddScriptLPS(1);
  220. if ((item = GetScriptByName(name)) != UUID.Zero)
  221. {
  222. return m_ScriptEngine.GetScriptState(item) ?1:0;
  223. }
  224. ShoutError("llGetScriptState: script "+name+" not found");
  225. // If we didn't find it, then it's safe to
  226. // assume it is not running.
  227. return 0;
  228. }
  229. public void llSetScriptState(string name, int run)
  230. {
  231. UUID item;
  232. m_host.AddScriptLPS(1);
  233. // These functions are supposed to be robust,
  234. // so get the state one step at a time.
  235. if ((item = GetScriptByName(name)) != UUID.Zero)
  236. {
  237. m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
  238. }
  239. else
  240. {
  241. ShoutError("llSetScriptState: script "+name+" not found");
  242. }
  243. }
  244. public List<SceneObjectPart> GetLinkParts(int linkType)
  245. {
  246. return GetLinkParts(m_host, linkType);
  247. }
  248. public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
  249. {
  250. List<SceneObjectPart> ret = new List<SceneObjectPart>();
  251. ret.Add(part);
  252. switch (linkType)
  253. {
  254. case ScriptBaseClass.LINK_SET:
  255. return new List<SceneObjectPart>(part.ParentGroup.Parts);
  256. case ScriptBaseClass.LINK_ROOT:
  257. ret = new List<SceneObjectPart>();
  258. ret.Add(part.ParentGroup.RootPart);
  259. return ret;
  260. case ScriptBaseClass.LINK_ALL_OTHERS:
  261. ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
  262. if (ret.Contains(part))
  263. ret.Remove(part);
  264. return ret;
  265. case ScriptBaseClass.LINK_ALL_CHILDREN:
  266. ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
  267. if (ret.Contains(part.ParentGroup.RootPart))
  268. ret.Remove(part.ParentGroup.RootPart);
  269. return ret;
  270. case ScriptBaseClass.LINK_THIS:
  271. return ret;
  272. default:
  273. if (linkType < 0)
  274. return new List<SceneObjectPart>();
  275. SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
  276. if (target == null)
  277. return new List<SceneObjectPart>();
  278. ret = new List<SceneObjectPart>();
  279. ret.Add(target);
  280. return ret;
  281. }
  282. }
  283. //These are the implementations of the various ll-functions used by the LSL scripts.
  284. public LSL_Float llSin(double f)
  285. {
  286. m_host.AddScriptLPS(1);
  287. return (double)Math.Sin(f);
  288. }
  289. public LSL_Float llCos(double f)
  290. {
  291. m_host.AddScriptLPS(1);
  292. return (double)Math.Cos(f);
  293. }
  294. public LSL_Float llTan(double f)
  295. {
  296. m_host.AddScriptLPS(1);
  297. return (double)Math.Tan(f);
  298. }
  299. public LSL_Float llAtan2(double x, double y)
  300. {
  301. m_host.AddScriptLPS(1);
  302. return (double)Math.Atan2(x, y);
  303. }
  304. public LSL_Float llSqrt(double f)
  305. {
  306. m_host.AddScriptLPS(1);
  307. return (double)Math.Sqrt(f);
  308. }
  309. public LSL_Float llPow(double fbase, double fexponent)
  310. {
  311. m_host.AddScriptLPS(1);
  312. return (double)Math.Pow(fbase, fexponent);
  313. }
  314. public LSL_Integer llAbs(int i)
  315. {
  316. // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
  317. m_host.AddScriptLPS(1);
  318. if (i == Int32.MinValue)
  319. return i;
  320. else
  321. return (int)Math.Abs(i);
  322. }
  323. public LSL_Float llFabs(double f)
  324. {
  325. m_host.AddScriptLPS(1);
  326. return (double)Math.Abs(f);
  327. }
  328. public LSL_Float llFrand(double mag)
  329. {
  330. m_host.AddScriptLPS(1);
  331. lock (Util.RandomClass)
  332. {
  333. return Util.RandomClass.NextDouble() * mag;
  334. }
  335. }
  336. public LSL_Integer llFloor(double f)
  337. {
  338. m_host.AddScriptLPS(1);
  339. return (int)Math.Floor(f);
  340. }
  341. public LSL_Integer llCeil(double f)
  342. {
  343. m_host.AddScriptLPS(1);
  344. return (int)Math.Ceiling(f);
  345. }
  346. // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
  347. public LSL_Integer llRound(double f)
  348. {
  349. m_host.AddScriptLPS(1);
  350. return (int)Math.Round(f, MidpointRounding.AwayFromZero);
  351. }
  352. //This next group are vector operations involving squaring and square root. ckrinke
  353. public LSL_Float llVecMag(LSL_Vector v)
  354. {
  355. m_host.AddScriptLPS(1);
  356. return LSL_Vector.Mag(v);
  357. }
  358. public LSL_Vector llVecNorm(LSL_Vector v)
  359. {
  360. m_host.AddScriptLPS(1);
  361. return LSL_Vector.Norm(v);
  362. }
  363. private double VecDist(LSL_Vector a, LSL_Vector b)
  364. {
  365. double dx = a.x - b.x;
  366. double dy = a.y - b.y;
  367. double dz = a.z - b.z;
  368. return Math.Sqrt(dx * dx + dy * dy + dz * dz);
  369. }
  370. public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
  371. {
  372. m_host.AddScriptLPS(1);
  373. return VecDist(a, b);
  374. }
  375. //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
  376. /// <summary>
  377. /// Convert an LSL rotation to a Euler vector.
  378. /// </summary>
  379. /// <remarks>
  380. /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
  381. /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
  382. /// </remarks>
  383. /// <param name="r"></param>
  384. /// <returns></returns>
  385. public LSL_Vector llRot2Euler(LSL_Rotation r)
  386. {
  387. m_host.AddScriptLPS(1);
  388. LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r.
  389. double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later.
  390. if (m == 0.0) return new LSL_Vector();
  391. double x = Math.Atan2(-v.y, v.z);
  392. double sin = v.x / m;
  393. if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
  394. double y = Math.Asin(sin);
  395. // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
  396. 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)));
  397. double z = Math.Atan2(v.y, v.x);
  398. return new LSL_Vector(x, y, z);
  399. }
  400. /* From wiki:
  401. The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
  402. in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
  403. a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
  404. vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
  405. */
  406. /* How we arrived at this llEuler2Rot
  407. *
  408. * Experiment in SL to determine conventions:
  409. * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
  410. * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
  411. * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
  412. *
  413. * Important facts about Quaternions
  414. * - multiplication is non-commutative (a*b != b*a)
  415. * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
  416. *
  417. * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
  418. * Qx = c1+i*s1
  419. * Qy = c2+j*s2;
  420. * Qz = c3+k*s3;
  421. *
  422. * Rotations applied in order (from above) Z, Y, X
  423. * Q = (Qz * Qy) * Qx
  424. * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
  425. * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
  426. * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
  427. * 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
  428. * 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
  429. * regroup: x=i*(s1*c2*c3+c1*s2*s3)
  430. * y=j*(c1*s2*c3-s1*c2*s3)
  431. * z=k*(s1*s2*c3+c1*c2*s3)
  432. * s= c1*c2*c3-s1*s2*s3
  433. *
  434. * This implementation agrees with the functions found here:
  435. * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
  436. * And with the results in SL.
  437. *
  438. * It's also possible to calculate llEuler2Rot by direct multiplication of
  439. * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
  440. * from the wiki).
  441. * Apparently in some cases this is better from a numerical precision perspective?
  442. */
  443. public LSL_Rotation llEuler2Rot(LSL_Vector v)
  444. {
  445. m_host.AddScriptLPS(1);
  446. double x,y,z,s;
  447. double c1 = Math.Cos(v.x * 0.5);
  448. double c2 = Math.Cos(v.y * 0.5);
  449. double c3 = Math.Cos(v.z * 0.5);
  450. double s1 = Math.Sin(v.x * 0.5);
  451. double s2 = Math.Sin(v.y * 0.5);
  452. double s3 = Math.Sin(v.z * 0.5);
  453. x = s1 * c2 * c3 + c1 * s2 * s3;
  454. y = c1 * s2 * c3 - s1 * c2 * s3;
  455. z = s1 * s2 * c3 + c1 * c2 * s3;
  456. s = c1 * c2 * c3 - s1 * s2 * s3;
  457. return new LSL_Rotation(x, y, z, s);
  458. }
  459. public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
  460. {
  461. m_host.AddScriptLPS(1);
  462. double s;
  463. double tr = fwd.x + left.y + up.z + 1.0;
  464. if (tr >= 1.0)
  465. {
  466. s = 0.5 / Math.Sqrt(tr);
  467. return new LSL_Rotation(
  468. (left.z - up.y) * s,
  469. (up.x - fwd.z) * s,
  470. (fwd.y - left.x) * s,
  471. 0.25 / s);
  472. }
  473. else
  474. {
  475. double max = (left.y > up.z) ? left.y : up.z;
  476. if (max < fwd.x)
  477. {
  478. s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
  479. double x = s * 0.5;
  480. s = 0.5 / s;
  481. return new LSL_Rotation(
  482. x,
  483. (fwd.y + left.x) * s,
  484. (up.x + fwd.z) * s,
  485. (left.z - up.y) * s);
  486. }
  487. else if (max == left.y)
  488. {
  489. s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
  490. double y = s * 0.5;
  491. s = 0.5 / s;
  492. return new LSL_Rotation(
  493. (fwd.y + left.x) * s,
  494. y,
  495. (left.z + up.y) * s,
  496. (up.x - fwd.z) * s);
  497. }
  498. else
  499. {
  500. s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
  501. double z = s * 0.5;
  502. s = 0.5 / s;
  503. return new LSL_Rotation(
  504. (up.x + fwd.z) * s,
  505. (left.z + up.y) * s,
  506. z,
  507. (fwd.y - left.x) * s);
  508. }
  509. }
  510. }
  511. public LSL_Vector llRot2Fwd(LSL_Rotation r)
  512. {
  513. m_host.AddScriptLPS(1);
  514. double x, y, z, m;
  515. m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  516. // m is always greater than zero
  517. // if m is not equal to 1 then Rotation needs to be normalized
  518. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  519. {
  520. m = 1.0 / Math.Sqrt(m);
  521. r.x *= m;
  522. r.y *= m;
  523. r.z *= m;
  524. r.s *= m;
  525. }
  526. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  527. x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
  528. y = 2 * (r.x * r.y + r.z * r.s);
  529. z = 2 * (r.x * r.z - r.y * r.s);
  530. return (new LSL_Vector(x, y, z));
  531. }
  532. public LSL_Vector llRot2Left(LSL_Rotation r)
  533. {
  534. m_host.AddScriptLPS(1);
  535. double x, y, z, m;
  536. m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  537. // m is always greater than zero
  538. // if m is not equal to 1 then Rotation needs to be normalized
  539. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  540. {
  541. m = 1.0 / Math.Sqrt(m);
  542. r.x *= m;
  543. r.y *= m;
  544. r.z *= m;
  545. r.s *= m;
  546. }
  547. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  548. x = 2 * (r.x * r.y - r.z * r.s);
  549. y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
  550. z = 2 * (r.x * r.s + r.y * r.z);
  551. return (new LSL_Vector(x, y, z));
  552. }
  553. public LSL_Vector llRot2Up(LSL_Rotation r)
  554. {
  555. m_host.AddScriptLPS(1);
  556. double x, y, z, m;
  557. m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  558. // m is always greater than zero
  559. // if m is not equal to 1 then Rotation needs to be normalized
  560. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  561. {
  562. m = 1.0 / Math.Sqrt(m);
  563. r.x *= m;
  564. r.y *= m;
  565. r.z *= m;
  566. r.s *= m;
  567. }
  568. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  569. x = 2 * (r.x * r.z + r.y * r.s);
  570. y = 2 * (-r.x * r.s + r.y * r.z);
  571. z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
  572. return (new LSL_Vector(x, y, z));
  573. }
  574. public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
  575. {
  576. //A and B should both be normalized
  577. m_host.AddScriptLPS(1);
  578. LSL_Rotation rotBetween;
  579. // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
  580. // continue calculation.
  581. if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
  582. {
  583. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  584. }
  585. else
  586. {
  587. a = LSL_Vector.Norm(a);
  588. b = LSL_Vector.Norm(b);
  589. double dotProduct = LSL_Vector.Dot(a, b);
  590. // There are two degenerate cases possible. These are for vectors 180 or
  591. // 0 degrees apart. These have to be detected and handled individually.
  592. //
  593. // Check for vectors 180 degrees apart.
  594. // A dot product of -1 would mean the angle between vectors is 180 degrees.
  595. if (dotProduct < -0.9999999f)
  596. {
  597. // First assume X axis is orthogonal to the vectors.
  598. LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
  599. orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
  600. // Check for near zero vector. A very small non-zero number here will create
  601. // a rotation in an undesired direction.
  602. if (LSL_Vector.Mag(orthoVector) > 0.0001)
  603. {
  604. rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f);
  605. }
  606. // If the magnitude of the vector was near zero, then assume the X axis is not
  607. // orthogonal and use the Z axis instead.
  608. else
  609. {
  610. // Set 180 z rotation.
  611. rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
  612. }
  613. }
  614. // Check for parallel vectors.
  615. // A dot product of 1 would mean the angle between vectors is 0 degrees.
  616. else if (dotProduct > 0.9999999f)
  617. {
  618. // Set zero rotation.
  619. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  620. }
  621. else
  622. {
  623. // All special checks have been performed so get the axis of rotation.
  624. LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
  625. // Quarternion s value is the length of the unit vector + dot product.
  626. double qs = 1.0 + dotProduct;
  627. rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
  628. // Normalize the rotation.
  629. double mag = LSL_Rotation.Mag(rotBetween);
  630. // We shouldn't have to worry about a divide by zero here. The qs value will be
  631. // non-zero because we already know if we're here, then the dotProduct is not -1 so
  632. // qs will not be zero. Also, we've already handled the input vectors being zero so the
  633. // crossProduct vector should also not be zero.
  634. rotBetween.x = rotBetween.x / mag;
  635. rotBetween.y = rotBetween.y / mag;
  636. rotBetween.z = rotBetween.z / mag;
  637. rotBetween.s = rotBetween.s / mag;
  638. // Check for undefined values and set zero rotation if any found. This code might not actually be required
  639. // any longer since zero vectors are checked for at the top.
  640. if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
  641. {
  642. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  643. }
  644. }
  645. }
  646. return rotBetween;
  647. }
  648. public void llWhisper(int channelID, string text)
  649. {
  650. m_host.AddScriptLPS(1);
  651. if (text.Length > 1023)
  652. text = text.Substring(0, 1023);
  653. World.SimChat(Utils.StringToBytes(text),
  654. ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
  655. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  656. if (wComm != null)
  657. wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
  658. }
  659. public void llSay(int channelID, string text)
  660. {
  661. m_host.AddScriptLPS(1);
  662. if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
  663. {
  664. Console.WriteLine(text);
  665. }
  666. else
  667. {
  668. if (text.Length > 1023)
  669. text = text.Substring(0, 1023);
  670. World.SimChat(Utils.StringToBytes(text),
  671. ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
  672. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  673. if (wComm != null)
  674. wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
  675. }
  676. }
  677. public void llShout(int channelID, string text)
  678. {
  679. m_host.AddScriptLPS(1);
  680. if (text.Length > 1023)
  681. text = text.Substring(0, 1023);
  682. World.SimChat(Utils.StringToBytes(text),
  683. ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
  684. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  685. if (wComm != null)
  686. wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
  687. }
  688. public void llRegionSay(int channelID, string text)
  689. {
  690. if (channelID == 0)
  691. {
  692. LSLError("Cannot use llRegionSay() on channel 0");
  693. return;
  694. }
  695. if (text.Length > 1023)
  696. text = text.Substring(0, 1023);
  697. m_host.AddScriptLPS(1);
  698. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  699. if (wComm != null)
  700. wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
  701. }
  702. public void llRegionSayTo(string target, int channel, string msg)
  703. {
  704. if (msg.Length > 1023)
  705. msg = msg.Substring(0, 1023);
  706. m_host.AddScriptLPS(1);
  707. if (channel == ScriptBaseClass.DEBUG_CHANNEL)
  708. {
  709. return;
  710. }
  711. UUID TargetID;
  712. UUID.TryParse(target, out TargetID);
  713. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  714. if (wComm != null)
  715. wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
  716. }
  717. public LSL_Integer llListen(int channelID, string name, string ID, string msg)
  718. {
  719. m_host.AddScriptLPS(1);
  720. UUID keyID;
  721. UUID.TryParse(ID, out keyID);
  722. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  723. if (wComm != null)
  724. return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg);
  725. else
  726. return -1;
  727. }
  728. public void llListenControl(int number, int active)
  729. {
  730. m_host.AddScriptLPS(1);
  731. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  732. if (wComm != null)
  733. wComm.ListenControl(m_item.ItemID, number, active);
  734. }
  735. public void llListenRemove(int number)
  736. {
  737. m_host.AddScriptLPS(1);
  738. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  739. if (wComm != null)
  740. wComm.ListenRemove(m_item.ItemID, number);
  741. }
  742. public void llSensor(string name, string id, int type, double range, double arc)
  743. {
  744. m_host.AddScriptLPS(1);
  745. UUID keyID = UUID.Zero;
  746. UUID.TryParse(id, out keyID);
  747. AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host);
  748. }
  749. public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
  750. {
  751. m_host.AddScriptLPS(1);
  752. UUID keyID = UUID.Zero;
  753. UUID.TryParse(id, out keyID);
  754. AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host);
  755. }
  756. public void llSensorRemove()
  757. {
  758. m_host.AddScriptLPS(1);
  759. AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID);
  760. }
  761. public string resolveName(UUID objecUUID)
  762. {
  763. // try avatar username surname
  764. UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID);
  765. if (account != null)
  766. {
  767. string avatarname = account.Name;
  768. return avatarname;
  769. }
  770. // try an scene object
  771. SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
  772. if (SOP != null)
  773. {
  774. string objectname = SOP.Name;
  775. return objectname;
  776. }
  777. EntityBase SensedObject;
  778. World.Entities.TryGetValue(objecUUID, out SensedObject);
  779. if (SensedObject == null)
  780. {
  781. IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
  782. if (groups != null)
  783. {
  784. GroupRecord gr = groups.GetGroupRecord(objecUUID);
  785. if (gr != null)
  786. return gr.GroupName;
  787. }
  788. return String.Empty;
  789. }
  790. return SensedObject.Name;
  791. }
  792. public LSL_String llDetectedName(int number)
  793. {
  794. m_host.AddScriptLPS(1);
  795. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  796. if (detectedParams == null)
  797. return String.Empty;
  798. return detectedParams.Name;
  799. }
  800. public LSL_String llDetectedKey(int number)
  801. {
  802. m_host.AddScriptLPS(1);
  803. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  804. if (detectedParams == null)
  805. return String.Empty;
  806. return detectedParams.Key.ToString();
  807. }
  808. public LSL_String llDetectedOwner(int number)
  809. {
  810. m_host.AddScriptLPS(1);
  811. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  812. if (detectedParams == null)
  813. return String.Empty;
  814. return detectedParams.Owner.ToString();
  815. }
  816. public LSL_Integer llDetectedType(int number)
  817. {
  818. m_host.AddScriptLPS(1);
  819. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  820. if (detectedParams == null)
  821. return 0;
  822. return new LSL_Integer(detectedParams.Type);
  823. }
  824. public LSL_Vector llDetectedPos(int number)
  825. {
  826. m_host.AddScriptLPS(1);
  827. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  828. if (detectedParams == null)
  829. return new LSL_Vector();
  830. return detectedParams.Position;
  831. }
  832. public LSL_Vector llDetectedVel(int number)
  833. {
  834. m_host.AddScriptLPS(1);
  835. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  836. if (detectedParams == null)
  837. return new LSL_Vector();
  838. return detectedParams.Velocity;
  839. }
  840. public LSL_Vector llDetectedGrab(int number)
  841. {
  842. m_host.AddScriptLPS(1);
  843. DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  844. if (parms == null)
  845. return new LSL_Vector(0, 0, 0);
  846. return parms.OffsetPos;
  847. }
  848. public LSL_Rotation llDetectedRot(int number)
  849. {
  850. m_host.AddScriptLPS(1);
  851. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  852. if (detectedParams == null)
  853. return new LSL_Rotation();
  854. return detectedParams.Rotation;
  855. }
  856. public LSL_Integer llDetectedGroup(int number)
  857. {
  858. m_host.AddScriptLPS(1);
  859. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  860. if (detectedParams == null)
  861. return new LSL_Integer(0);
  862. if (m_host.GroupID == detectedParams.Group)
  863. return new LSL_Integer(1);
  864. return new LSL_Integer(0);
  865. }
  866. public LSL_Integer llDetectedLinkNumber(int number)
  867. {
  868. m_host.AddScriptLPS(1);
  869. DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
  870. if (parms == null)
  871. return new LSL_Integer(0);
  872. return new LSL_Integer(parms.LinkNum);
  873. }
  874. /// <summary>
  875. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
  876. /// </summary>
  877. public LSL_Vector llDetectedTouchBinormal(int index)
  878. {
  879. m_host.AddScriptLPS(1);
  880. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
  881. if (detectedParams == null)
  882. return new LSL_Vector();
  883. return detectedParams.TouchBinormal;
  884. }
  885. /// <summary>
  886. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
  887. /// </summary>
  888. public LSL_Integer llDetectedTouchFace(int index)
  889. {
  890. m_host.AddScriptLPS(1);
  891. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
  892. if (detectedParams == null)
  893. return new LSL_Integer(-1);
  894. return new LSL_Integer(detectedParams.TouchFace);
  895. }
  896. /// <summary>
  897. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
  898. /// </summary>
  899. public LSL_Vector llDetectedTouchNormal(int index)
  900. {
  901. m_host.AddScriptLPS(1);
  902. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
  903. if (detectedParams == null)
  904. return new LSL_Vector();
  905. return detectedParams.TouchNormal;
  906. }
  907. /// <summary>
  908. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
  909. /// </summary>
  910. public LSL_Vector llDetectedTouchPos(int index)
  911. {
  912. m_host.AddScriptLPS(1);
  913. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
  914. if (detectedParams == null)
  915. return new LSL_Vector();
  916. return detectedParams.TouchPos;
  917. }
  918. /// <summary>
  919. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
  920. /// </summary>
  921. public LSL_Vector llDetectedTouchST(int index)
  922. {
  923. m_host.AddScriptLPS(1);
  924. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
  925. if (detectedParams == null)
  926. return new LSL_Vector(-1.0, -1.0, 0.0);
  927. return detectedParams.TouchST;
  928. }
  929. /// <summary>
  930. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
  931. /// </summary>
  932. public LSL_Vector llDetectedTouchUV(int index)
  933. {
  934. m_host.AddScriptLPS(1);
  935. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
  936. if (detectedParams == null)
  937. return new LSL_Vector(-1.0, -1.0, 0.0);
  938. return detectedParams.TouchUV;
  939. }
  940. public virtual void llDie()
  941. {
  942. m_host.AddScriptLPS(1);
  943. throw new SelfDeleteException();
  944. }
  945. public LSL_Float llGround(LSL_Vector offset)
  946. {
  947. m_host.AddScriptLPS(1);
  948. Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
  949. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
  950. LSL_Vector vsn = llGroundNormal(offset);
  951. // Clamp to valid position
  952. if (pos.X < 0)
  953. pos.X = 0;
  954. else if (pos.X >= World.Heightmap.Width)
  955. pos.X = World.Heightmap.Width - 1;
  956. if (pos.Y < 0)
  957. pos.Y = 0;
  958. else if (pos.Y >= World.Heightmap.Height)
  959. pos.Y = World.Heightmap.Height - 1;
  960. //Get the height for the integer coordinates from the Heightmap
  961. float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y];
  962. //Calculate the difference between the actual coordinates and the integer coordinates
  963. float xdiff = pos.X - (float)((int)pos.X);
  964. float ydiff = pos.Y - (float)((int)pos.Y);
  965. //Use the equation of the tangent plane to adjust the height to account for slope
  966. return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight;
  967. }
  968. public LSL_Float llCloud(LSL_Vector offset)
  969. {
  970. m_host.AddScriptLPS(1);
  971. float cloudCover = 0f;
  972. ICloudModule module = World.RequestModuleInterface<ICloudModule>();
  973. if (module != null)
  974. {
  975. Vector3 pos = m_host.GetWorldPosition();
  976. int x = (int)(pos.X + offset.x);
  977. int y = (int)(pos.Y + offset.y);
  978. cloudCover = module.CloudCover(x, y, 0);
  979. }
  980. return cloudCover;
  981. }
  982. public LSL_Vector llWind(LSL_Vector offset)
  983. {
  984. m_host.AddScriptLPS(1);
  985. LSL_Vector wind = new LSL_Vector(0, 0, 0);
  986. IWindModule module = World.RequestModuleInterface<IWindModule>();
  987. if (module != null)
  988. {
  989. Vector3 pos = m_host.GetWorldPosition();
  990. int x = (int)(pos.X + offset.x);
  991. int y = (int)(pos.Y + offset.y);
  992. Vector3 windSpeed = module.WindSpeed(x, y, 0);
  993. wind.x = windSpeed.X;
  994. wind.y = windSpeed.Y;
  995. }
  996. return wind;
  997. }
  998. public void llSetStatus(int status, int value)
  999. {
  1000. m_host.AddScriptLPS(1);
  1001. int statusrotationaxis = 0;
  1002. if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
  1003. {
  1004. if (value != 0)
  1005. {
  1006. SceneObjectGroup group = m_host.ParentGroup;
  1007. bool allow = true;
  1008. foreach (SceneObjectPart part in group.Parts)
  1009. {
  1010. if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
  1011. {
  1012. allow = false;
  1013. break;
  1014. }
  1015. }
  1016. if (!allow)
  1017. return;
  1018. m_host.ScriptSetPhysicsStatus(true);
  1019. }
  1020. else
  1021. {
  1022. m_host.ScriptSetPhysicsStatus(false);
  1023. }
  1024. }
  1025. if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
  1026. {
  1027. m_host.ParentGroup.ScriptSetPhantomStatus(value != 0);
  1028. }
  1029. if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
  1030. {
  1031. m_host.AddFlag(PrimFlags.CastShadows);
  1032. }
  1033. if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
  1034. {
  1035. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
  1036. }
  1037. if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
  1038. {
  1039. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
  1040. }
  1041. if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
  1042. {
  1043. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
  1044. }
  1045. if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
  1046. {
  1047. if (value != 0)
  1048. m_host.SetBlockGrab(true);
  1049. else
  1050. m_host.SetBlockGrab(false);
  1051. }
  1052. if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
  1053. {
  1054. if (value != 0)
  1055. m_host.SetDieAtEdge(true);
  1056. else
  1057. m_host.SetDieAtEdge(false);
  1058. }
  1059. if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
  1060. {
  1061. if (value != 0)
  1062. m_host.SetReturnAtEdge(true);
  1063. else
  1064. m_host.SetReturnAtEdge(false);
  1065. }
  1066. if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
  1067. {
  1068. if (value != 0)
  1069. m_host.SetStatusSandbox(true);
  1070. else
  1071. m_host.SetStatusSandbox(false);
  1072. }
  1073. if (statusrotationaxis != 0)
  1074. {
  1075. m_host.SetAxisRotation(statusrotationaxis, value);
  1076. }
  1077. }
  1078. private bool IsPhysical()
  1079. {
  1080. return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics);
  1081. }
  1082. public LSL_Integer llGetStatus(int status)
  1083. {
  1084. m_host.AddScriptLPS(1);
  1085. // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
  1086. switch (status)
  1087. {
  1088. case ScriptBaseClass.STATUS_PHYSICS:
  1089. return IsPhysical() ? 1 : 0;
  1090. case ScriptBaseClass.STATUS_PHANTOM:
  1091. if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
  1092. {
  1093. return 1;
  1094. }
  1095. return 0;
  1096. case ScriptBaseClass.STATUS_CAST_SHADOWS:
  1097. if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
  1098. {
  1099. return 1;
  1100. }
  1101. return 0;
  1102. case ScriptBaseClass.STATUS_BLOCK_GRAB:
  1103. if (m_host.GetBlockGrab())
  1104. return 1;
  1105. else
  1106. return 0;
  1107. case ScriptBaseClass.STATUS_DIE_AT_EDGE:
  1108. if (m_host.GetDieAtEdge())
  1109. return 1;
  1110. else
  1111. return 0;
  1112. case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
  1113. if (m_host.GetReturnAtEdge())
  1114. return 1;
  1115. else
  1116. return 0;
  1117. case ScriptBaseClass.STATUS_ROTATE_X:
  1118. // if (m_host.GetAxisRotation(2) != 0)
  1119. if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
  1120. return 1;
  1121. else
  1122. return 0;
  1123. case ScriptBaseClass.STATUS_ROTATE_Y:
  1124. if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
  1125. return 1;
  1126. else
  1127. return 0;
  1128. case ScriptBaseClass.STATUS_ROTATE_Z:
  1129. if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
  1130. return 1;
  1131. else
  1132. return 0;

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