Jump to content

Magnet script


Orabelle
 Share

Recommended Posts

Can someone help me with a magnetic type script? If that's what you would call it. Something to pull avatars towards an object. I've done tons of searching, but I've only managed to find one old script, which doesn't really fit my needs. I've tried editing it, but I had no luck, being a novice at scripting.

I just want the most simple script I can find.
- Needs to attract avatars only, no objects
- Ability to change radius and force (so needs to be mod)
- Needs to start on entry, I have no need to stop it.
- No asking permissions (it won't be an annoyance)

It'd be great if someone can lend me a hand.

Link to comment
Share on other sites

I doubt that you will be able to write a script that will apply an attractive force on an unscripted avatar.  LSL has a llPushObject function, but no equivalent llPullObject.  If the avatar is seated, however, you can apply a force to the seat or simply move it toward a target location with llMoveToTarget.  That would have the same visual effect as applying an attractive force, but without much of a surprise element.

Link to comment
Share on other sites

I can imagine it being possible, I've seen something like it before. Someone I know in world used it for his shop once, much like described, it pulled people in, and without confirmation, sitting, or scripts on our side. I'll be sure to ask him about it when I see him next, but there's no guarantee that he'd help.

Link to comment
Share on other sites

So I've made some progress messing with this a little bit. I've got the attraction going on, without any permissions or anything like that. I'm trying to figure out how to start this however, currently it's touch_start, but I'm not liking that. What alternate methods could I use? :matte-motes-bashful-cute-2:

Link to comment
Share on other sites

It is possible. Would be a variation of the infamous cage thingy. Make a transparent physical cage around an avatar then move it to target...with the "content" inside. A cage could be made on collision by firing a lil bullet at a nearby avatar. But I don't want to make a thingy like that, even if asked nicely :)

Link to comment
Share on other sites

llPushObject will do the job certainly, the only difference between attraction (magnet) and repulsion is a matter of direction anyway, so the calculation is simple enough. There are some interesting notes in the Wiki regarding its effect over distance. I can see some fun applications (theme parks etc) where, if done with consent, it would be neat (with the usual push enable flag, landowner caveats), however - any shop using such a thing on me without consent would see my pocket money walking away =^^=

Link to comment
Share on other sites

touch_start (and touch_end and touch) are events, not functions.  They are simply blocks of code that respond to a left mouse click.  What you do in an event determines the response.  If you want a simple toggle switch ..

 

integer gON;default{     touch_start(integer num)    {        if (!gON)        {            // Do something (or don't)        }        else        {            // Don't do something (or do it)        }        gON = !gON;    }}

 

 

Link to comment
Share on other sites

How do you mean, you need a start function?    If you're using llPushObject() you need to grab the key of whoever or whatever you are pushing, so touch_start is only going to work if your victim touches something.   You could use collision_start or a sensor, or, I guess, you could grab their key in a listen event.

Link to comment
Share on other sites

Apart from the fact that I wouldn't use this script ever...controlling an avatars motion without asking.... I'd use a sensor(repeat), triggered in the state_entry. You need that function anyway to stop the magnet once the avatar is close enough.  I do expect quite some issues with multiple avatars at the same time though. I'm not the most experienced scripter, but I would think you need to make a list of all avatars sensed, then scroll through that list all the time while making the interval of the sensor dependant on the numbers of avatars around.

Link to comment
Share on other sites

I agree.  I wouldn't use this script on any avatars without their prior consent either.  Turning it on and off is a simple matter, though.  As you, Innula, and I have said, the OP could build a toggle into any event she wishes (touch_start, collision_start, timer, sensor, changed, listen, run_time_permission..... ), depending on how she wants to trigger it. 

Link to comment
Share on other sites

Ok, I'm not sure what I'm doing at this point. Lol.
I'll post what I have so far, maybe you could help me from there.
It's a little messy.

I appreciate all the help, hope I'm not too much of a bother. :matte-motes-wink:

 

float RADIUS = 3.0;float FORCE = 5.0;integer AVATARS = TRUE;integer OBJECTS = FALSE;integer listener;default {    state_entry() {    }     // !! These touch_starts need to be replaced !!     // !! with something else, that's where I'm stuck !!     // - Either needs to be always active, OR     // - Script starts when avatar is close enough     //       touch_start(integer touches) {        // turn the magnet on        if (llDetectedKey(0) == llGetOwner()) state magnetized;    }}state magnetized {    on_rez(integer start) {        llResetScript();    }         state_entry() {          integer types;        if (AVATARS) types = types | AGENT;        if (OBJECTS) types = types | ACTIVE;               llSensorRepeat("", "", types, RADIUS, TWO_PI, 0.1);                      }         touch_start(integer touches) {        key toucher = llDetectedKey(0);        if (toucher == llGetOwner()) state default;       }    sensor(integer sensed) {        integer i;                 for (i = 0; i < sensed; i ++) {            key target_key = llDetectedKey(i);                        // the position of our target            vector target_pos = llDetectedPos(i);            vector my_pos = llGetPos();                        // normalized vector describing the direction            // from our target to us            // this is a negative vector            // which will draw the object towards us            vector direction = llVecNorm(my_pos - target_pos);                        // apply set amount of force            // in the direction from the target to this object            vector impulse = FORCE * direction;                        // equalize for the targets mass so pull is consistent            impulse *= llGetObjectMass(target_key);                        // equalize for the distance of the target            // so pull is consistent            impulse *= llPow(llVecDist(my_pos, target_pos), 3.0);                        // negate the targets current velocity            impulse -= llDetectedVel(i);                        llPushObject(target_key, impulse, ZERO_VECTOR, FALSE);        }    }}

 

Link to comment
Share on other sites

That's a decent start.  Here are a few things to think about ...

1.  You won't be able to set the sensor for avatars and objects at the same time, so you don't actually need both AVATARS and OBJECTS.  Just choose one as the default and switch to the other when you want to.

integer gAvatars;  // Here's your global integer variable that you use as the toggle

Then in state magnetized ...

 

state_entry(){    if (gAvatars) // That is, if you have selected to scan for avatars....    {        llSensorRepeat("","",AGENT, gRadius, PI, 0.1);    }   else  //That is, you have set gAvatars to FALSE because you are scanning for objects instead ...    {        llSensorRepeat("","",ACTIVE, gRadius,PI,0.1);    }}

 2.  The touch_start events are a perfectly good way to switch states and thus turn the device on and off.  The only thing you are missing is the actual OFF command, which is llSensorRemove().  That belongs in state_entry in your default state, so that switching back there automatically kills the sensor.

Those are the two big things.   Beyond that, there are stylistic things to consider...

3.  You don't need the listener variable, because you aren't listening for anything.

4. Note that the sensor doesn't need to scan for TWO_PI radians. PI scans the entire sphere.

5.  It's usually good practice to avoid naming variables in ALL CAPS, because that's the way LL names system constants. You might have the bad luck to choose a name that is already taken, and you'd be scratching your head about the error message for a while.

6. It's good to get in the habit of always putting curly brackets around the scope of an if test.  In this script, you get away with omitting them because the scope in each case is a single command.  Sooner or later, though, you will modify a script like this and add another command or two, forgetting that the brackets are missing.  When that happens, only the first command will be affected by the if.  I think it's a lot easier to just remember to always put the brackets there, whether they are strictly required or not.

 

 

Link to comment
Share on other sites

Changing the integers somehow messed the script up and it stopped working, so I left that the way it was.
I replaced the state_entry in magnetized like you showed.
I removed the listener variable.

That's as much as I've managed. I tried altering it further, but I failed in doing anything else. :matte-motes-confused:

Link to comment
Share on other sites

So I managed to get the script my friend was using.. (He wouldn't even take my money, how nice. lol) It turns out he pretty much made the same exact thing as I was, except he had the final result, where as I was stuck. The help I received here on the forum was great, I was even able to improve his a bit. I doubt I'll have much use for this script, really, but the main purpose was to learn a bit. On to the next. :matte-motes-wink-tongue:


EDIT: I put the script on the market if anyone's interested. "Magnetic Script"

Link to comment
Share on other sites

  • 3 years later...

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...