Jump to content
Tattooshop

Hand greanade

Recommended Posts

Posted (edited)

Hey. how in theory to simulate a grenade explosion, pushing avatars away in a certain range?

I mean pushing itself.

Edited by Tattooshop

Share this post


Link to post
Share on other sites

In theory?

        llPushObject(kAv,6000.0*llGetObjectMass(kAv)*(vAvPos - llGetPos()),ZERO_VECTOR,FALSE);

and trigger that in a sensor event when kAv is detected within your target range.

But that will only work if the region allows pushing or if the object is pushing the owner. If you are working in an Experience, you could of course auto-attach a temporary object an then move it (and the avatar) rapidly away from the grenade, with all the appropriate noise and particle FX. 

  • Thanks 1

Share this post


Link to post
Share on other sites

another way is

when the grenade explodes have it rez a transparent physical object, using the rotation and velocity parameters of llRezObject to throw the rezzed object at the target avatar. Being physical, the avatar will get bumped/moved when the object collides with them

http://wiki.secondlife.com/wiki/LlRezObject

 

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
7 minutes ago, Mollymews said:

when the grenade explodes have it rez a temp_on_rez transparent physical object

otherwise it may end up three regions away and you may be yelled at for littering.  🙄

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
20 hours ago, Rolig Loon said:

In theory?

        llPushObject(kAv,6000.0*llGetObjectMass(kAv)*(vAvPos - llGetPos()),ZERO_VECTOR,FALSE);

and trigger that in a sensor event when kAv is detected within your target range.

But that will only work if the region allows pushing or if the object is pushing the owner. If you are working in an Experience, you could of course auto-attach a temporary object an then move it (and the avatar) rapidly away from the grenade, with all the appropriate noise and particle FX. 

 

18 hours ago, Mollymews said:

another way is

when the grenade explodes have it rez a transparent physical object, using the rotation and velocity parameters of llRezObject to throw the rezzed object at the target avatar. Being physical, the avatar will get bumped/moved when the object collides with them

http://wiki.secondlife.com/wiki/LlRezObject

 

Hello! Thank you both very much!  :)

So now I am trying llPushObject and thats what I got but it says "Type mismatch"... And what is vAvPos here? :D

integer vAvPos;

default
{
    state_entry()
    {
        llSensor("", NULL_KEY, AGENT, 3.0, PI);
    }
 
    sensor(integer detected)
    {
        llPushObject(llDetectedKey(0), 6000.0*llGetObjectMass(llDetectedKey(0))*(vAvPos - llGetPos()), ZERO_VECTOR, FALSE);
    }
}

Thank you again very much! 💖

Share this post


Link to post
Share on other sites

Oh, well, you do have to define AvPos = llDetectedPos(0);

Most of that second argument in llPushObject is my way of creating a plausible fudge factor for the magnitude of the push. llGetObjectMass() gives me a way to scale the push to the mass of the person that the object is supposed to push.  And the factor of 6000 is simply an empirical scale factor that seems to work for me.  It pushes most people a pleasing distance.  YMMV.  And then, of course (AvPos - llGetPos()) is the vector along which the push is to be applied.

  • Thanks 1

Share this post


Link to post
Share on other sites
4 hours ago, Rolig Loon said:

Oh, well, you do have to define AvPos = llDetectedPos(0);

Most of that second argument in llPushObject is my way of creating a plausible fudge factor for the magnitude of the push. llGetObjectMass() gives me a way to scale the push to the mass of the person that the object is supposed to push.  And the factor of 6000 is simply an empirical scale factor that seems to work for me.  It pushes most people a pleasing distance.  YMMV.  And then, of course (AvPos - llGetPos()) is the vector along which the push is to be applied.

Awesomeness!! works great! but for some reason it repels only one avatar (the one who is closer). But how to make it to repel everyone in the range? :D

default
{
    state_entry()
    {
        llSensor("", NULL_KEY, AGENT, 5.0, PI);
    }
 
    sensor(integer detected)
    {
        llPushObject(llDetectedKey(0), 6000.0*llGetObjectMass(llDetectedKey(0))*(llDetectedPos(0) - llGetPos()), ZERO_VECTOR, FALSE);
    }
}

 

Share this post


Link to post
Share on other sites
Posted (edited)
5 minutes ago, Tattooshop said:

But how to make it to repel everyone in the range?

You have to pay attention to more than just llDetectedKey(0).  A sensor can detect up to 16 avatars within range. So just loop through all detected avatars from 0 to the maximum detected and shove them all.

http://wiki.secondlife.com/wiki/LlSensor#Examples

Edited by Rolig Loon
  • Thanks 1

Share this post


Link to post
Share on other sites
13 hours ago, Rolig Loon said:

You have to pay attention to more than just llDetectedKey(0).  A sensor can detect up to 16 avatars within range. So just loop through all detected avatars from 0 to the maximum detected and shove them all.

http://wiki.secondlife.com/wiki/LlSensor#Examples

Thanks a lot! I learned a new trick! Now it repels even physical objects of small mass! :D

But as before, it is not possible to make this work for several objects and avatars. What is my mistake?

default
{
    touch_start(integer total_number)
    {
        llSensor("", NULL_KEY, (AGENT | PASSIVE), 5.0, PI);
    }

    sensor(integer detected)
    {
        while (detected--)
        {
            llPushObject(llDetectedKey(0), 6000.0 * llGetObjectMass(llDetectedKey(0)) * (llDetectedPos(0) - llGetPos()), ZERO_VECTOR, FALSE);
        }
    }
}

 

Share this post


Link to post
Share on other sites

You should be using the variable detected in each of the llDetected*** functions, rather than just 0. This tells the llDetected*** function which of the detected objects you're interested in.

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
2 hours ago, KT Kingsley said:

You should be using the variable detected in each of the llDetected*** functions, rather than just 0. This tells the llDetected*** function which of the detected objects you're interested in.

Thanks a lot! in combination with this grenade thrower script and explosion particles system and sounds, a good grenade was obtained! :D

default
{
    state_entry()
    {
        llSetTimerEvent(3);
    }

    sensor(integer detected)
    {
        while (detected--)
        {
            llPushObject(llDetectedKey(detected), 6000.0 * llGetObjectMass(llDetectedKey(detected)) * (llDetectedPos(detected) - llGetPos()), ZERO_VECTOR, FALSE);
            llSleep(1);
            llDie();
        }
    }
    
    timer()
    {
        llSensor("", NULL_KEY, (AGENT | PASSIVE), 5.0, PI);
    }
}

 

Share this post


Link to post
Share on other sites

I see a problem with that script: the llDie() statement is inside the loop. The loop will execute once for the highest number detected object and then die before it can push any of the other detected objects. Also, the llSleep function will be executed for every iteration of the loop.

I think what you want is:

    sensor(integer detected)
    {
        while (detected--)
        {
            llPushObject(llDetectedKey(detected), 6000.0 * llGetObjectMass(llDetectedKey(detected)) * (llDetectedPos(detected) - llGetPos()), ZERO_VECTOR, FALSE);
        }
        llSleep(1);
        llDie();
    }
  • Thanks 1

Share this post


Link to post
Share on other sites
18 hours ago, Rolig Loon said:

You have to pay attention to more than just llDetectedKey(0).  A sensor can detect up to 16 avatars within range. So just loop through all detected avatars from 0 to the maximum detected and shove them all.

http://wiki.secondlife.com/wiki/LlSensor#Examples

 

2 hours ago, KT Kingsley said:

I see a problem with that script: the llDie() statement is inside the loop. The loop will execute once for the highest number detected object and then die before it can push any of the other detected objects. Also, the llSleep function will be executed for every iteration of the loop.

I think what you want is:


    sensor(integer detected)
    {
        while (detected--)
        {
            llPushObject(llDetectedKey(detected), 6000.0 * llGetObjectMass(llDetectedKey(detected)) * (llDetectedPos(detected) - llGetPos()), ZERO_VECTOR, FALSE);
        }
        llSleep(1);
        llDie();
    }

There is a ridiculous problem. :D

I can’t get the grenade script to work from the time of the throw.


-- I rez a grenade.

-- I put the script there. and the script starts working, the timer starts and I have to very quickly grab the grenade and pick it up in my inventory until it explodes and put it in the Thrower object.

But the timer counts down from the moment when I scripted it. And the grenade explodes "ahead of time". How to make the script or timer reset and the countdown start from the moment of the throw?

 

Share this post


Link to post
Share on other sites
string EXPLODE3 = "fd5e5c93-691c-eadb-ee27-8972af741823";

iParticles()
{
llParticleSystem([PSYS_PART_MAX_AGE,1.50,
PSYS_PART_FLAGS, 291,
PSYS_PART_START_COLOR, <0, 0, 0>,
PSYS_PART_END_COLOR, <1, 1, 1>,
PSYS_PART_START_SCALE,<1.01000, 1.01000, 0.00000>,
PSYS_PART_END_SCALE,<1.91139, 2.00179, 0.00000>,
PSYS_SRC_PATTERN, 2,
PSYS_SRC_BURST_RATE,0.00,
PSYS_SRC_BURST_PART_COUNT,4,
PSYS_SRC_BURST_RADIUS,0.30,
PSYS_SRC_BURST_SPEED_MIN,0.10,
PSYS_SRC_BURST_SPEED_MAX,2.06,
PSYS_SRC_ANGLE_BEGIN, 3.14,
PSYS_SRC_ANGLE_END, 0.00,
PSYS_SRC_MAX_AGE, 0.0,
PSYS_SRC_TEXTURE, "74e8631c-33a9-bc1a-03d3-ede886272a21",
PSYS_PART_START_ALPHA, 0.79,
PSYS_PART_END_ALPHA, 0.00,
PSYS_PART_START_GLOW, 0.06,
PSYS_PART_END_GLOW, 0.00]);
}

default
{
    state_entry()
    {
        llParticleSystem([]);
        llSetTimerEvent(3);
    }
    
    on_rez(integer num)
    {
        llResetScript();
    }

    sensor(integer detected)
    {
        while (detected--)
        {
            llPushObject(llDetectedKey(detected), 6000.0 * llGetObjectMass(llDetectedKey(detected)) * (llDetectedPos(detected) - llGetPos()), ZERO_VECTOR, FALSE);
        }

        llSleep(1);
        llTriggerSound(EXPLODE3, 1.0);
        llTriggerSound(EXPLODE3, 1.0);
        llTriggerSound(EXPLODE3, 1.0);
        llDie();
    }
    
    timer()
    {
        iParticles();
        llSensor("", NULL_KEY, (AGENT | PASSIVE), 5.0, PI);
    }
}

 

Share this post


Link to post
Share on other sites

I managed to do everything quite quickly, so the problem was solved. but if there is any way to do this through a script, please share it! :) Thank you all again!

Share this post


Link to post
Share on other sites
Posted (edited)

How does the thrower object work?

Does it rez the grenade with a velocity, using llRezObject or llRezAtRoot? Or is it something like a physical catapult?

One thing you could try is to have the timer start when the grenade is rezzed, in the on_rez event, rather than when the script is saved or reset, in the state_entry event:

    state_entry()
    {
        llParticleSystem([]);
    }
    
    on_rez(integer num)
    {
        llSetTimerEvent(3);
    }
//etc...

Edit: I just saw your link to the thrower script, and it does use llRezAtRoot, so I think my suggestion above should do the trick.

Edited by KT Kingsley
Deleted commented out llRestScript call to avoid confusion.
  • Thanks 1

Share this post


Link to post
Share on other sites
Posted (edited)
29 minutes ago, KT Kingsley said:

How does the thrower object work?

Does it rez the grenade with a velocity, using llRezObject or llRezAtRoot? Or is it something like a physical catapult?

One thing you could try is to have the timer start when the grenade is rezzed, in the on_rez event, rather than when the script is saved or reset, in the state_entry event:


    state_entry()
    {
        llParticleSystem([]);
    }
    
    on_rez(integer num)
    {
//        llResetScript();
        llSetTimerEvent(3);
    }
//etc...

Edit: I just saw your link to the thrower script, and it does use llRezAtRoot, so I think my suggestion above should do the trick.

As someone who's made a small bunch of stuff for combat, a script reset should be unnecessary and would only prolong the "initialization period" of the grenade.

That specific example would also never start a timer. The script will exit the event before it can set the timer, and the timer would disappear even if the lines were swapped.

Edit: Oh, I literally didn't even spot the comment-slashes.

Edited by Wulfie Reanimator
  • Thanks 1

Share this post


Link to post
Share on other sites

Oh, and so as not to start the timer when you rez the grenade from your inventory to edit it, you could test if the on_rez parameter is not 0 (the llRezAtRoot functions in the thrower script set a parameter of either 1 or 10, depending on the mode).

So:

    on_rez(integer num)
    {
        if (num) llSetTimerEvent(3);
    }
  • Thanks 1

Share this post


Link to post
Share on other sites
1 minute ago, Wulfie Reanimator said:

As someone who's made a small bunch of stuff for combat, a script reset should be unnecessary and would only prolong the "initialization period" of the grenade.

That specific example would also never start a timer. The script will exit the event before it can set the timer, and the timer would disappear even if the lines were swapped.

In that example I did comment out the redundant llResetScript call. I'll edit my post to delete it altogether, to avoid confusion.

  • Thanks 1

Share this post


Link to post
Share on other sites

And, I just noticed, you'll need a no_sensor event in the grenade script for when your aim is off (or you're just playing around) and the grenade lands more than 5 metres away from an avatar.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
1 hour ago, KT Kingsley said:

And, I just noticed, you'll need a no_sensor event in the grenade script for when your aim is off (or you're just playing around) and the grenade lands more than 5 metres away from an avatar.

Woah! This is super cool!  😎

Yes, no_sensor event was really missing! I'm not sure that I did everything right but it works great for now! Thanks a lot! 💖

string EXPLODE3 = "fd5e5c93-691c-eadb-ee27-8972af741823";

iParticles()
{
llParticleSystem([PSYS_PART_MAX_AGE,1.50,
PSYS_PART_FLAGS, 291,
PSYS_PART_START_COLOR, <0, 0, 0>,
PSYS_PART_END_COLOR, <1, 1, 1>,
PSYS_PART_START_SCALE,<1, 1, 0>,
PSYS_PART_END_SCALE,<4, 4, 0>,
PSYS_SRC_PATTERN, 2,
PSYS_SRC_BURST_RATE,0.00,
PSYS_SRC_BURST_PART_COUNT,20,
PSYS_SRC_BURST_RADIUS,0.30,
PSYS_SRC_BURST_SPEED_MIN,0.10,
PSYS_SRC_BURST_SPEED_MAX,5.00,
PSYS_SRC_ANGLE_BEGIN, 3.14,
PSYS_SRC_ANGLE_END, 0.00,
PSYS_SRC_MAX_AGE, 0.0,
PSYS_SRC_TEXTURE, "74e8631c-33a9-bc1a-03d3-ede886272a21",
PSYS_PART_START_ALPHA, 0.80,
PSYS_PART_END_ALPHA, 0.00,
PSYS_PART_START_GLOW, 0.05,
PSYS_PART_END_GLOW, 0.00]);
}

default
{
    state_entry()
    {
        llParticleSystem([]);
    }
    
    on_rez(integer num)
    {
        llSetTimerEvent(3);
    }

    sensor(integer detected)
    {
        while (detected--)
        {
            llPushObject(llDetectedKey(detected), 6000.0 * llGetObjectMass(llDetectedKey(detected)) * (llDetectedPos(detected) - llGetPos()), ZERO_VECTOR, FALSE);
        }

        llSleep(1);
        llDie();
    }
    
    no_sensor()
    {
        iParticles();
        llTriggerSound(EXPLODE3, 1.0);
        llTriggerSound(EXPLODE3, 1.0);
        llTriggerSound(EXPLODE3, 1.0);
        llSleep(1);
        llDie();
    }
    
    timer()
    {
        iParticles();        
        llSensor("", NULL_KEY, (AGENT | PASSIVE), 5.0, PI);
        llTriggerSound(EXPLODE3, 1.0);
        llTriggerSound(EXPLODE3, 1.0);
        llTriggerSound(EXPLODE3, 1.0);
    }
}

 

  • Like 1

Share this post


Link to post
Share on other sites

I’ll just notice that I duplicated llTriggerSound and particles in no_sensor by mistake, because the particles and sound seem to go even without it. :D

 

Share this post


Link to post
Share on other sites
Posted (edited)

@Rolig Loon

I apologize for pulling you into this topic again. But is it possible to somehow start the process without a sensor with a timer, since it is already here?
I tried to move the line

llPushObject(llDetectedKey(detected), 6000.0 * llGetObjectMass(llDetectedKey(detected)) * (llDetectedPos(detected) - llGetPos()), ZERO_VECTOR, FALSE);

to timer event but I didn’t succeed. :)

 

Edited by Tattooshop

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...