aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs51
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs119
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs101
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs41
5 files changed, 188 insertions, 134 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 0ec9575..831922e 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -757,64 +757,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
757 757
758 SceneObjectGroup group = null; 758 SceneObjectGroup group = null;
759 759
760 string xmlData = Utils.BytesToString(rezAsset.Data); 760 List<SceneObjectGroup> objlist;
761 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); 761 List<Vector3> veclist;
762 List<Vector3> veclist = new List<Vector3>(); 762 Vector3 bbox;
763 float offsetHeight;
763 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 764 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
764 Vector3 pos; 765 Vector3 pos;
765 766
766 XmlDocument doc = new XmlDocument(); 767 bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
767 doc.LoadXml(xmlData);
768 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
769 if (e == null || attachment) // Single
770 {
771 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
772
773 objlist.Add(g);
774 veclist.Add(Vector3.Zero);
775 768
776 float offsetHeight = 0; 769 if (single)
770 {
777 pos = m_Scene.GetNewRezLocation( 771 pos = m_Scene.GetNewRezLocation(
778 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 772 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
779 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); 773 BypassRayCast, bRayEndIsIntersection, true, bbox, false);
780 pos.Z += offsetHeight; 774 pos.Z += offsetHeight;
781 } 775 }
782 else 776 else
783 { 777 {
784 XmlElement coll = (XmlElement)e;
785 float bx = Convert.ToSingle(coll.GetAttribute("x"));
786 float by = Convert.ToSingle(coll.GetAttribute("y"));
787 float bz = Convert.ToSingle(coll.GetAttribute("z"));
788 Vector3 bbox = new Vector3(bx, by, bz);
789
790 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, 778 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
791 RayTargetID, Quaternion.Identity, 779 RayTargetID, Quaternion.Identity,
792 BypassRayCast, bRayEndIsIntersection, true, 780 BypassRayCast, bRayEndIsIntersection, true,
793 bbox, false); 781 bbox, false);
794
795 pos -= bbox / 2; 782 pos -= bbox / 2;
796
797 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
798 foreach (XmlNode n in groups)
799 {
800 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
801
802 objlist.Add(g);
803 XmlElement el = (XmlElement)n;
804
805 string rawX = el.GetAttribute("offsetx");
806 string rawY = el.GetAttribute("offsety");
807 string rawZ = el.GetAttribute("offsetz");
808//
809// m_log.DebugFormat(
810// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
811// g.Name, rawX, rawY, rawZ);
812
813 float x = Convert.ToSingle(rawX);
814 float y = Convert.ToSingle(rawY);
815 float z = Convert.ToSingle(rawZ);
816 veclist.Add(new Vector3(x, y, z));
817 }
818 } 783 }
819 784
820 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) 785 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 150193d..9ffda51 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -234,15 +234,17 @@ namespace OpenSim.Region.Framework.Interfaces
234 List<TaskInventoryItem> GetInventoryItems(InventoryType type); 234 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
235 235
236 /// <summary> 236 /// <summary>
237 /// Get the scene object referenced by an inventory item. 237 /// Get the scene object(s) referenced by an inventory item.
238 /// </summary> 238 /// </summary>
239 /// 239 ///
240 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have 240 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
241 /// been adjusted to reflect the part and item from which it originates. 241 /// been adjusted to reflect the part and item from which it originates.
242 /// 242 ///
243 /// <param name="item"></param> 243 /// <param name="item">Inventory item</param>
244 /// <returns>The scene object. Null if the scene object asset couldn't be found</returns> 244 /// <param name="objlist">The scene objects</param>
245 SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item); 245 /// <param name="veclist">Relative offsets for each object</param>
246 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
247 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist);
246 248
247 /// <summary> 249 /// <summary>
248 /// Update an existing inventory item. 250 /// Update an existing inventory item.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 4bebbe8..65536db 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -31,6 +31,7 @@ using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36using log4net; 37using log4net;
@@ -2135,6 +2136,69 @@ namespace OpenSim.Region.Framework.Scenes
2135 } 2136 }
2136 2137
2137 /// <summary> 2138 /// <summary>
2139 /// Returns the list of Scene Objects in an asset.
2140 /// </summary>
2141 /// <remarks>
2142 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2143 /// </remarks>
2144 /// <param name="assetData">Asset data</param>
2145 /// <param name="attachment">Whether the item is an attachment</param>
2146 /// <param name="objlist">The objects included in the asset</param>
2147 /// <param name="veclist">Relative positions of the objects</param>
2148 /// <param name="bbox">Bounding box of all the objects</param>
2149 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2150 /// to the centre of the root prim (relevant only when returning a single object)</param>
2151 /// <returns>true = returning a single object; false = multiple objects</returns>
2152 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2153 out Vector3 bbox, out float offsetHeight)
2154 {
2155 objlist = new List<SceneObjectGroup>();
2156 veclist = new List<Vector3>();
2157
2158 XmlDocument doc = new XmlDocument();
2159 string xmlData = Utils.BytesToString(assetData);
2160 doc.LoadXml(xmlData);
2161 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2162
2163 if (e == null || attachment) // Single
2164 {
2165 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2166 objlist.Add(g);
2167 veclist.Add(new Vector3(0, 0, 0));
2168 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2169 return true;
2170 }
2171 else
2172 {
2173 XmlElement coll = (XmlElement)e;
2174 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2175 float by = Convert.ToSingle(coll.GetAttribute("y"));
2176 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2177 bbox = new Vector3(bx, by, bz);
2178 offsetHeight = 0;
2179
2180 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2181 foreach (XmlNode n in groups)
2182 {
2183 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2184 objlist.Add(g);
2185
2186 XmlElement el = (XmlElement)n;
2187 string rawX = el.GetAttribute("offsetx");
2188 string rawY = el.GetAttribute("offsety");
2189 string rawZ = el.GetAttribute("offsetz");
2190
2191 float x = Convert.ToSingle(rawX);
2192 float y = Convert.ToSingle(rawY);
2193 float z = Convert.ToSingle(rawZ);
2194 veclist.Add(new Vector3(x, y, z));
2195 }
2196 }
2197
2198 return false;
2199 }
2200
2201 /// <summary>
2138 /// Event Handler Rez an object into a scene 2202 /// Event Handler Rez an object into a scene
2139 /// Calls the non-void event handler 2203 /// Calls the non-void event handler
2140 /// </summary> 2204 /// </summary>
@@ -2209,19 +2273,25 @@ namespace OpenSim.Region.Framework.Scenes
2209 /// will be used if it exists.</param> 2273 /// will be used if it exists.</param>
2210 /// <param name="vel">The velocity of the rezzed object.</param> 2274 /// <param name="vel">The velocity of the rezzed object.</param>
2211 /// <param name="param"></param> 2275 /// <param name="param"></param>
2212 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2276 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2213 public virtual SceneObjectGroup RezObject( 2277 public virtual List<SceneObjectGroup> RezObject(
2214 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2278 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2215 { 2279 {
2216 if (null == item) 2280 if (null == item)
2217 return null; 2281 return null;
2282
2283 List<SceneObjectGroup> objlist;
2284 List<Vector3> veclist;
2218 2285
2219 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2286 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2220 2287 if (!success)
2221 if (null == group)
2222 return null; 2288 return null;
2223 2289
2224 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2290 int totalPrims = 0;
2291 foreach (SceneObjectGroup group in objlist)
2292 totalPrims += group.PrimCount;
2293
2294 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2225 return null; 2295 return null;
2226 2296
2227 if (!Permissions.BypassPermissions()) 2297 if (!Permissions.BypassPermissions())
@@ -2230,23 +2300,28 @@ namespace OpenSim.Region.Framework.Scenes
2230 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2300 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2231 } 2301 }
2232 2302
2233 2303 for (int i = 0; i < objlist.Count; i++)
2234 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2235 { 2304 {
2236 group.RootPart.AttachedPos = group.AbsolutePosition; 2305 SceneObjectGroup group = objlist[i];
2237 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; 2306 Vector3 curpos = pos + veclist[i];
2307
2308 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2309 {
2310 group.RootPart.AttachedPos = group.AbsolutePosition;
2311 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2312 }
2313
2314 group.FromPartID = sourcePart.UUID;
2315 AddNewSceneObject(group, true, curpos, rot, vel);
2316
2317 // We can only call this after adding the scene object, since the scene object references the scene
2318 // to find out if scripts should be activated at all.
2319 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2320
2321 group.ScheduleGroupForFullUpdate();
2238 } 2322 }
2239 2323
2240 group.FromPartID = sourcePart.UUID; 2324 return objlist;
2241 AddNewSceneObject(group, true, pos, rot, vel);
2242
2243 // We can only call this after adding the scene object, since the scene object references the scene
2244 // to find out if scripts should be activated at all.
2245 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2246
2247 group.ScheduleGroupForFullUpdate();
2248
2249 return group;
2250 } 2325 }
2251 2326
2252 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2327 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3f223a3..380e402 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -733,8 +733,8 @@ namespace OpenSim.Region.Framework.Scenes
733 733
734 return items; 734 return items;
735 } 735 }
736 736
737 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) 737 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
738 { 738 {
739 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 739 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
740 740
@@ -743,66 +743,75 @@ namespace OpenSim.Region.Framework.Scenes
743 m_log.WarnFormat( 743 m_log.WarnFormat(
744 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 744 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
745 item.AssetID, item.Name, m_part.Name); 745 item.AssetID, item.Name, m_part.Name);
746 return null; 746 objlist = null;
747 veclist = null;
748 return false;
747 } 749 }
748 750
749 string xmlData = Utils.BytesToString(rezAsset.Data); 751 Vector3 bbox;
750 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 752 float offsetHeight;
751 753
752 group.ResetIDs(); 754 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
753 755
754 SceneObjectPart rootPart = group.GetPart(group.UUID); 756 for (int i = 0; i < objlist.Count; i++)
757 {
758 SceneObjectGroup group = objlist[i];
755 759
756 // Since renaming the item in the inventory does not affect the name stored 760 group.ResetIDs();
757 // in the serialization, transfer the correct name from the inventory to the
758 // object itself before we rez.
759 rootPart.Name = item.Name;
760 rootPart.Description = item.Description;
761 761
762 SceneObjectPart[] partList = group.Parts; 762 SceneObjectPart rootPart = group.GetPart(group.UUID);
763 763
764 group.SetGroup(m_part.GroupID, null); 764 // Since renaming the item in the inventory does not affect the name stored
765 // in the serialization, transfer the correct name from the inventory to the
766 // object itself before we rez.
767 rootPart.Name = item.Name;
768 rootPart.Description = item.Description;
765 769
766 // TODO: Remove magic number badness 770 SceneObjectPart[] partList = group.Parts;
767 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 771
768 { 772 group.SetGroup(m_part.GroupID, null);
769 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) 773
774 // TODO: Remove magic number badness
775 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
770 { 776 {
771 foreach (SceneObjectPart part in partList) 777 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
772 { 778 {
773 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 779 foreach (SceneObjectPart part in partList)
774 part.EveryoneMask = item.EveryonePermissions; 780 {
775 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) 781 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
776 part.NextOwnerMask = item.NextPermissions; 782 part.EveryoneMask = item.EveryonePermissions;
777 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) 783 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
778 part.GroupMask = item.GroupPermissions; 784 part.NextOwnerMask = item.NextPermissions;
785 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
786 part.GroupMask = item.GroupPermissions;
787 }
788
789 group.ApplyNextOwnerPermissions();
779 } 790 }
780
781 group.ApplyNextOwnerPermissions();
782 } 791 }
783 }
784 792
785 foreach (SceneObjectPart part in partList) 793 foreach (SceneObjectPart part in partList)
786 {
787 // TODO: Remove magic number badness
788 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
789 { 794 {
790 part.LastOwnerID = part.OwnerID; 795 // TODO: Remove magic number badness
791 part.OwnerID = item.OwnerID; 796 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
792 part.Inventory.ChangeInventoryOwner(item.OwnerID); 797 {
798 part.LastOwnerID = part.OwnerID;
799 part.OwnerID = item.OwnerID;
800 part.Inventory.ChangeInventoryOwner(item.OwnerID);
801 }
802
803 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
804 part.EveryoneMask = item.EveryonePermissions;
805 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
806 part.NextOwnerMask = item.NextPermissions;
807 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
808 part.GroupMask = item.GroupPermissions;
793 } 809 }
794 810
795 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 811 rootPart.TrimPermissions();
796 part.EveryoneMask = item.EveryonePermissions;
797 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
798 part.NextOwnerMask = item.NextPermissions;
799 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
800 part.GroupMask = item.GroupPermissions;
801 } 812 }
802 813
803 rootPart.TrimPermissions(); 814 return true;
804
805 return group;
806 } 815 }
807 816
808 /// <summary> 817 /// <summary>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 975bf2d..b19ed0a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2970,37 +2970,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2970 // need the magnitude later 2970 // need the magnitude later
2971 // float velmag = (float)Util.GetMagnitude(llvel); 2971 // float velmag = (float)Util.GetMagnitude(llvel);
2972 2972
2973 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); 2973 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
2974 2974
2975 // If either of these are null, then there was an unknown error. 2975 // If either of these are null, then there was an unknown error.
2976 if (new_group == null) 2976 if (new_groups == null)
2977 return; 2977 return;
2978 2978
2979 // objects rezzed with this method are die_at_edge by default. 2979 foreach (SceneObjectGroup group in new_groups)
2980 new_group.RootPart.SetDieAtEdge(true); 2980 {
2981 // objects rezzed with this method are die_at_edge by default.
2982 group.RootPart.SetDieAtEdge(true);
2981 2983
2982 new_group.ResumeScripts(); 2984 group.ResumeScripts();
2983 2985
2984 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 2986 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
2985 "object_rez", new Object[] { 2987 "object_rez", new Object[] {
2986 new LSL_String( 2988 new LSL_String(
2987 new_group.RootPart.UUID.ToString()) }, 2989 group.RootPart.UUID.ToString()) },
2988 new DetectParams[0])); 2990 new DetectParams[0]));
2989 2991
2990 float groupmass = new_group.GetMass(); 2992 float groupmass = group.GetMass();
2991 2993
2992 PhysicsActor pa = new_group.RootPart.PhysActor; 2994 PhysicsActor pa = group.RootPart.PhysActor;
2993 2995
2994 //Recoil. 2996 //Recoil.
2995 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 2997 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
2996 {
2997 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
2998 if (recoil != Vector3.Zero)
2999 { 2998 {
3000 llApplyImpulse(recoil, 0); 2999 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3000 if (recoil != Vector3.Zero)
3001 {
3002 llApplyImpulse(recoil, 0);
3003 }
3001 } 3004 }
3005 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3002 } 3006 }
3003 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3004 }); 3007 });
3005 3008
3006 //ScriptSleep((int)((groupmass * velmag) / 10)); 3009 //ScriptSleep((int)((groupmass * velmag) / 10));