public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
{
m_host.AddScriptLPS(1);
bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing;
bool pushAllowed = false;
bool pusheeIsAvatar = false;
UUID targetID = UUID.Zero;
if (!UUID.TryParse(target,out targetID))
return;
ScenePresence pusheeav = null;
Vector3 PusheePos = Vector3.Zero;
SceneObjectPart pusheeob = null;
ScenePresence avatar = World.GetScenePresence(targetID);
if (avatar != null)
{
pusheeIsAvatar = true;
// Pushee doesn't have a physics actor
if (avatar.PhysicsActor == null)
return;
// 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?
SceneObjectPart sitPart = pusheeav.ParentPart;
if (sitPart != null)
PusheePos = sitPart.AbsolutePosition;
else
PusheePos = pusheeav.AbsolutePosition;
}
if (!pusheeIsAvatar)
{
// not an avatar so push is not affected by parcel flags
pusheeob = World.GetSceneObjectPart((UUID)target);
// We can't find object
if (pusheeob == null)
return;
// Object not pushable. Not an attachment and has no physics component
if (!pusheeob.ParentGroup.IsAttachment && pusheeob.PhysActor == null)
return;
PusheePos = pusheeob.AbsolutePosition;
pushAllowed = true;
}
else
{
if (pushrestricted)
{
ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
// We didn't find the parcel but region is push restricted so assume it is NOT ok
if (targetlandObj == null)
return;
// Need provisions for Group Owned here
if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID)
{
pushAllowed = true;
}
}
else
{
ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
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
if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject)
{
// Need provisions for Group Owned here
if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
targetlandObj.LandData.IsGroupOwned ||
m_host.OwnerID == targetID)
{
pushAllowed = true;
}
//ParcelFlags.RestrictPushObject
//pushAllowed = true;
}
else
{
// Parcel isn't push restricted
pushAllowed = true;
}
}
}
}
if (pushAllowed)
{
float distance = (PusheePos - m_host.AbsolutePosition).Length();
float distance_term = distance * distance * distance; // Script Energy
// use total object mass and not part
float pusher_mass = m_host.ParentGroup.GetMass();
float PUSH_ATTENUATION_DISTANCE = 17f;
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 = impulse;
{
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();
applied_linear_impulse *= pusheeav.GetWorldRotation();
}
pa.AddForce(applied_linear_impulse, true);
}
}
}
else
{
if (pusheeob != null)
{
if (pusheeob.PhysActor != null)
{
pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
}
}
}
}
}