public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local) { if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) { return; } bool pushAllowed = false; bool pusheeIsAvatar = false; UUID targetID = UUID.Zero; if (!UUID.TryParse(target, out targetID)) { return; } IScenePresence pusheeav = null; Vector3 PusheePos = Vector3.Zero; ISceneChildEntity pusheeob = null; IScenePresence avatar = World.GetScenePresence(targetID); if (avatar != null) { pusheeIsAvatar = true; // Pushee is in GodMode this pushing object isn't owned by them if (avatar.GodLevel > 0 && m_host.OwnerID != targetID) { return; } pusheeav = avatar; // Find pushee position // Pushee Linked? if (pusheeav.ParentID != UUID.Zero) { ISceneChildEntity parentobj = World.GetSceneObjectPart(pusheeav.ParentID); PusheePos = parentobj != null ? parentobj.AbsolutePosition : pusheeav.AbsolutePosition; } else { PusheePos = pusheeav.AbsolutePosition; } } if (!pusheeIsAvatar) { // not an avatar so push is not affected by parcel flags pusheeob = World.GetSceneObjectPart(UUID.Parse(target)); // We can't find object if (pusheeob == null) { return; } // Object not pushable. Not an attachment and has no physics component if (!pusheeob.IsAttachment && pusheeob.PhysActor == null) { return; } PusheePos = pusheeob.AbsolutePosition; pushAllowed = true; } else { IParcelManagementModule parcelManagement = World.RequestModuleInterface <IParcelManagementModule>(); if (World.RegionInfo.RegionSettings.RestrictPushing) { pushAllowed = m_host.OwnerID == targetID || m_host.ParentEntity.Scene.Permissions.IsGod(m_host.OwnerID); } else { if (parcelManagement != null) { ILandObject targetlandObj = parcelManagement.GetLandObject(PusheePos.X, PusheePos.Y); if (targetlandObj == null) { // We didn't find the parcel but region isn't push restricted so assume it's ok pushAllowed = true; } else { // Parcel push restriction pushAllowed = (targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) != (uint)ParcelFlags.RestrictPushObject || m_host.ParentEntity.Scene.Permissions.CanPushObject(m_host.OwnerID, targetlandObj); } } } } if (pushAllowed) { float distance = (PusheePos - m_host.AbsolutePosition).Length(); float distance_term = distance * distance * distance; // Script Energy float pusher_mass = m_host.GetMass(); const float PUSH_ATTENUATION_DISTANCE = 17f; const float PUSH_ATTENUATION_SCALE = 5f; float distance_attenuation = 1f; if (distance > PUSH_ATTENUATION_DISTANCE) { float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE; distance_attenuation = 1f / normalized_units; } Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); { float impulse_length = applied_linear_impulse.Length(); float desired_energy = impulse_length * pusher_mass; if (desired_energy > 0f) { desired_energy += distance_term; } float scaling_factor = 1f; scaling_factor *= distance_attenuation; applied_linear_impulse *= scaling_factor; } if (pusheeIsAvatar) { if (pusheeav != null) { PhysicsActor pa = pusheeav.PhysicsActor; if (pa != null) { if (local != 0) { applied_linear_impulse *= m_host.GetWorldRotation(); } //Put a limit on it... int MaxPush = (int)pusheeav.PhysicsActor.Mass * 25; if (applied_linear_impulse.X > 0 && Math.Abs(applied_linear_impulse.X) > MaxPush) { applied_linear_impulse.X = MaxPush; } if (applied_linear_impulse.X < 0 && Math.Abs(applied_linear_impulse.X) > MaxPush) { applied_linear_impulse.X = -MaxPush; } if (applied_linear_impulse.Y > 0 && Math.Abs(applied_linear_impulse.X) > MaxPush) { applied_linear_impulse.Y = MaxPush; } if (applied_linear_impulse.Y < 0 && Math.Abs(applied_linear_impulse.Y) > MaxPush) { applied_linear_impulse.Y = -MaxPush; } if (applied_linear_impulse.Z > 0 && Math.Abs(applied_linear_impulse.X) > MaxPush) { applied_linear_impulse.Z = MaxPush; } if (applied_linear_impulse.Z < 0 && Math.Abs(applied_linear_impulse.Z) > MaxPush) { applied_linear_impulse.Z = -MaxPush; } pa.AddForce(applied_linear_impulse, true); } } } else { if (pusheeob.PhysActor != null) { pusheeob.ApplyImpulse(applied_linear_impulse, local != 0); } } } }