I have a script (below) that attempts to use llPushObject to drag avatars along in a moving building. Attach it to any non-physical flat horizontal prim, touch to start then stand (not sit) on it. It kind of works (with all the llPushObject problems mentioned above). It might work for a floating dance floor where you don’t care if people drift back and forth a bit. A transparent wall around the edges keeps people from being pushed off by all the problems.
Any suggestions on a better way to do this? Something like llApplyImpulse that works on avatars? Ideally all I really need is llSetObjectPos or llSetObjectDetails. It is frustrating to think that I can do this simulated physical friction if only I had a non-physical SetPos that worked on avatars! Now that I think of it, I seem to spend most of my time trying to circumvent what little physics we do have in SL!
//Rotate test
// Test the feasibility of making a non-physical object
//that moves and drags (pushes) avatars along with it
//sort of like friction would
// attach to a platform, touch to start/stop rotation
//then stand (don't sit) on the platform.
// The platform slides around in a circle (just to
//generate some motion), your avatar should be
//taken with it.
vector cent; //center when rotation starts
float radius=4.0; //radius of rotation
vector lpos; //last position around circle track
vector npos=<4.0,0.,0.>; //next position
float angle=0.03; //rotation quanta
float sa; //sine and cosine of rotation quanta
float ca;
float delT=0.2; //time step
float range; //radius of bounding box
default
{
state_entry()
{
llSay(0, "Click to start/stop rotation"
;cent = llGetPos()-<radius,0.,0.>;
sa = llSin(angle);
ca = llCos(angle);
list box = llGetBoundingBox(llGetKey());
vector size = llList2Vector(box, 1) - llList2Vector(box, 0);
range=llSqrt(llPow(size.x,2.0)+llPow(size.y,2.0))/2.0;
}
touch_start(integer total_number)
{
state rotate;
}
}
state rotate
{
state_entry()
{
llSetTimerEvent(delT);
}
timer()
{
lpos = npos; //save last positon for delta
npos.x=lpos.x*ca+lpos.y*sa; //calculate a new position
npos.y=lpos.y*ca-lpos.x*sa;
llSensor("","",AGENT,range,PI); //move any nearby agents
llSetPos(cent+npos); //move the platform
}
sensor(integer num)
{
integer i=0;
while (i<num)
{
key AV=llDetectedKey(i); //get avatar mass, position, velocity
float mass=llGetObjectMass(AV);
list a = llGetObjectDetails(AV, ([OBJECT_VELOCITY,OBJECT_POS]));
vector Avel=llList2Vector(a,0);
vector Apos=llList2Vector(a,1);
float dist=llVecDist(llGetPos(),Apos);
float comp=llPow(dist,3); //compensate for pushobjects 1/(r^3)
vector Dvel=(npos-lpos)/delT; //desired velocity vector
llPushObject(AV,Dvel*comp*mass/6.0,<0.,0,0.>,FALSE);
i += 1;
}
}
touch_start(integer total_number)
{
state default;
}
}