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.PhysicsActor != 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.X) > 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;
pusheeav.PhysicsActor.AddForce(applied_linear_impulse, true);
}
}
else
{
if (pusheeob.PhysActor != null)
{
pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
}
}
}
}