Jump to content

Help! I'm having particle & sensor issues!


Tenaar Feiri
 Share

You are about to reply to a thread that has been inactive for 4173 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hey y'all! I'm currently trying to write a script that shoots a burst of particles toward any agent who comes within 5m of an object, but I'm really having trouble with the sensor event.

The code I'm writing is designed to randomly pick a number between 0 & 1000 every 4 hours, and then alter the states depending on the result between "safe", in which no particles will be spewed at an  unsuspecting passersby, and "unsafe" where it will fire at will.

 

I've almost gotten it to work the way I want to, but I'm having one big issue: The particles are only going off once, and then the sensor event appears to die (along with the timer), and it completely halts the script & requires a manual reset.

 

What I need the script to do is to continuously launch bursts of particles at nearby avatars, and stop launching those bursts when it gets out of range.

 

Could I have a little help with it please? :3

 

(For the curious, this script is meant for roleplaying purposes with scripted NPCs. I also should be able to do the targeting on my own; I'm currently most concerned with getting the base script to work right. I'm also incredibly sorry about how messy it is; I apparently can't control states as global events. >.>)

 

 

Script enclosed:

 

//////////////////////////////////////////////
// Particle spitter script.
// By Tenaar Feiri.
//////////////////////////////////////////////


////////////////////////////Particle scripts!/////////////////////

// SECTION ONE: APPEARANCE -- These settings affect how each particle LOOKS.
integer      glow = TRUE;        // TRUE or FALSE(*)
vector startColor = <1,0,0>;     // RGB color, black<0,0,0> to white<1,1,1>(*)
vector   endColor = <1,0,0>;     // 
float  startAlpha = 1.0;         // 0.0 to 1.0(*), lower = more transparent
float    endAlpha = 1.0;         // 
vector  startSize = <0.1,0.1,0>; // <0.04,0.04,0>(min) to <10,10,0>(max>, <1,1,0>(*)
vector    endSize = <0.1,0.1,0>; // (Z part of vector is discarded)  
key     texture = "419c3949-3f56-6115-5f1c-1f3aa85a4606";          // Texture used for particles. Texture must be in prim's inventory.

// SECTION TWO: FLOW -- These settings affect how Many, how Quickly, and for how Long particles are created.
//     Note, 
integer count = 5;    // Number of particles created per burst, 1(*) to 4096
float    rate = 0.1;   // Delay between bursts of new particles, 0.0 to 60, 0.1(*)
float     age = 3.0;   // How long each particle lives, 0.1 to 60, 10.0(*)
float    life = 2.0;   // When to stop creating new particles. never stops if 0.0(*)

// SECTION THREE: PLACEMENT -- Where are new particles created, and what direction are they facing?
float      radius = .30;      // 0.0(default) to 64?  Distance from Emitter where new particles are created.
float  innerAngle = 0.75;  // "spread", for all ANGLE patterns, 0(default) to PI
float  outerAngle = 0.0;        // "tilt", for ANGLE patterns,  0(default) to TWO_PI, can use PI_BY_TWO or PI as well.
integer   pattern = PSYS_SRC_PATTERN_ANGLE_CONE; // Choose one of the following:
                // PSYS_SRC_PATTERN_EXPLODE (sends particles in all directions)
                // PSYS_SRC_PATTERN_DROP  (ignores minSpeed and maxSpeed.  Don't bother with count>1 )
                // PSYS_SRC_PATTERN_ANGLE_CONE (set innerangle/outerange to make rings/cones of particles)
                // PSYS_SRC_PATTERN_ANGLE (set innerangle/outerangle to make flat fanshapes of particles)
vector      omega = <0,0,0>; // How much to rotate the emitter around the <X,Y,Z> axises. <0,0,0>(*)
                             // Warning, there's no way to RESET the emitter direction once you use Omega!!
                             // You must attach the script to a new prim to clear the effect of omega.

// SECTION FOUR: MOVEMENT -- How do the particles move once they're created?
integer followSource = FALSE;   // TRUE or FALSE(*), Particles move as the emitter moves, (TRUE disables radius!)
integer    followVel = FALSE;    // TRUE or FALSE(*), Particles rotate towards their direction
integer         wind = FALSE;   // TRUE or FALSE(*), Particles get blown away by wind in the sim
integer       bounce = FALSE;   // TRUE or FALSE(*), Make particles bounce on Z altitude of emitter
float       minSpeed = 1.3;     // 0.01 to ? Min speed each particle is spit out at, 1.0(*)
float       maxSpeed = 1.5;     // 0.01 to ? Max speed each particle is spit out at, 1.0(*)
vector          push = <0,0,-0.6>; // Continuous force pushed on particles, use small settings for long lived particles
key           target = "";      // Select a target for particles to arrive at when they die
                                // can be "self" (emitter), "owner" (you), "" or any prim/persons KEY.

// Script variables

integer flags;
list sys;

updateParticles()
{
    flags = 0;
    if (target == "owner") target = llGetOwner();
    if (target == "self") target = llGetKey();
    if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK;
    if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK;
    if (startColor != endColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
    if (startSize != endSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK;
    if (wind) flags = flags | PSYS_PART_WIND_MASK;
    if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK;
    if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK;
    if (target != "") flags = flags | PSYS_PART_TARGET_POS_MASK;
    sys = [  PSYS_PART_MAX_AGE,age,
                        PSYS_PART_FLAGS,flags,
                        PSYS_PART_START_COLOR, startColor,
                        PSYS_PART_END_COLOR, endColor,
                        PSYS_PART_START_SCALE,startSize,
                        PSYS_PART_END_SCALE,endSize, 
                        PSYS_SRC_PATTERN, pattern,
                        PSYS_SRC_BURST_RATE,rate,
                        PSYS_SRC_ACCEL, push,
                        PSYS_SRC_BURST_PART_COUNT,count,
                        PSYS_SRC_BURST_RADIUS,radius,
                        PSYS_SRC_BURST_SPEED_MIN,minSpeed,
                        PSYS_SRC_BURST_SPEED_MAX,maxSpeed,
                        PSYS_SRC_TARGET_KEY,target,
                        PSYS_SRC_INNERANGLE,innerAngle, 
                        PSYS_SRC_OUTERANGLE,outerAngle,
                        PSYS_SRC_OMEGA, omega,
                        PSYS_SRC_MAX_AGE, life,
                        PSYS_SRC_TEXTURE, texture,
                        PSYS_PART_START_ALPHA, startAlpha,
                        PSYS_PART_END_ALPHA, endAlpha
                            ];
    float newrate = rate;
    if (newrate == 0.0) newrate=.01;
    if ( (age/rate)*count < 4096) llParticleSystem(sys);
    else {
        llInstantMessage(llGetOwner(),"Your particle system creates too many concurrent particles.");
        llInstantMessage(llGetOwner(),"Reduce count or age, or increase rate.");
        llParticleSystem( [ ] );
    }
}


integer switch=0;
key name;





////////////////////////Timer scripts!////////////////////////////



// Define the numerous variables.

key gUUID = ""; // Admin to IM if someone crosses the boundaries.

float timeLimit = 15; // Timer reset limit (in seconds). Default: 14400 (4 hours).

float Number; // Float.

float safeguard; // To help tell the reset script what to do.

integer rand(integer max)
{
    float f_max = (float)max;//we do this typecast explicitly (otherwise the compiler just fills it in for us.
    if(max != f_max)//max was an integer that couldn't be made into a float nicely.
        return (integer)(max * llFrand(1.0));//multiply max by a rand float with a 0->1 range.
    return (integer)llFrand(f_max);//the convert was clean so make LSL do the work.
}

// Typecast a float to a string.
string float2string(float Number) {
    string result=(string)Number;
    integer i=llStringLength(result);
    while(llGetSubString(result,--i,i)=="0");
    result = llDeleteSubString(result,i+1,llStringLength(result));
    integer dot = llStringLength(result)-1;
    if(llGetSubString(result,dot,dot) == ".") result = llDeleteSubString(result,dot,dot);
    return result;
}




/////////Execute!//////////

// Start by generating a random number.
default
{
        // When the default state is entered, begin randomization.
        state_entry()
        {
             switch==0;
    if(switch==0)
        {
            
            llSensorRemove();
            llSay(0,"Hearts off");
            llParticleSystem( [ ] );
        }
           float Number = rand(1000); // Random number between 0 & 1000.
                    // If the result is less than 300, make the object safe.
            if(Number <= 300)
            {
            float safeguard = 0;
        
                // For debugging purposes, tell the owner the result.
                llOwnerSay((string)Number);
                state wSafe;
            }
            
            // If the result is more than 600, make the object unsafe.
            else if(Number >= 600)
            {
            float safeguard = 1;
                // Snitch about the number. Debugging.
                llOwnerSay((string)Number);
                state unsafe;

            }
            
            else
            {
            
                state restart;
            
            }
           
        }
}


// Safe mode!
state wSafe
{
    state_entry()
    {
    llParticleSystem( [ ] );
    switch==0;
    if(switch==0)
        {
            
            llSensorRemove();
            llSay(0,"Hearts off");
            llParticleSystem( [ ] );
        }
        // For testing.
        llOwnerSay("We're in safe mode!");
        
        // Set the string so we know where we are.
        string nState = "safe";
        
        // Set the timer event.
        llSetTimerEvent(timeLimit);
    }
        no_sensor()
     {
          llParticleSystem( [ ] );
     }
    
    
    // Check the timer!
    timer()
    {
            // Stop the timer event to prevent lag.
        llSetTimerEvent(0.0);
        // For debugging.
        llOwnerSay("Generating...");
        
        float Number = rand(1000); // Random number between 0 & 1000.
                    // If the result is less than 300, make the object safe.
            if(Number <= 300)
            {
            // Set the string so we know where we are.
        //string nState = "safe";
        
        float safeguard = 0;
                // For debugging purposes, tell the owner the result.
                llOwnerSay((string)Number);
                
                state restart;
            }
            
            // If the result is more than 600, make the object unsafe.
            else if(Number >= 600)
            {
            // Set the string so we know where we are.
        //string nState = "unsafe";
        float safeguard = 1;
                // Snitch about the number. Debugging.
                llOwnerSay((string)Number);
                
                state unsafe;
            }
            
            else
            {
            
                state restart;
            
            }
    
    
    }


            
}


// Unsafe mode!
state unsafe
{
    state_entry()
    {
llParticleSystem( [ ] );
        // For testing.
        llOwnerSay("We're in unsafe mode!");
        
        // For testing.
        name = llGetOwner();
        
        // Set the timer event.
        llSetTimerEvent(timeLimit);
        
        //llSensor("", NULL_KEY, AGENT_BY_LEGACY_NAME, 30.0, PI);
        
        // Begin particles!
        
        if(switch==0)
        {
            switch=1;
            llSensorRepeat("","",AGENT_BY_LEGACY_NAME,5.0,PI,2.0);
            llSay(0,"Hearts on");
        }
        
        
    }
    sensor(integer num_detected)
    {
        
           
        if(num_detected && switch==1)
        {
            updateParticles();
            float safeguard = 1;
            llSleep(timeLimit);
            state restart;
        }
        
        
        
        
        
        
    }
    no_sensor()
     {
          llParticleSystem( [ ] );
     }
        
  

    
    
    // Check the timer!
    timer()
    {
    
    // Stop the timer event to prevent lag.
        llSetTimerEvent(0.0);
        // For debugging.
        llOwnerSay("Generating...");
        
        float Number = rand(1000); // Random number between 0 & 1000.
                    // If the result is less than 300, make the object safe.
            if(Number <= 300)
            {
            // Set the string so we know where we are.
        //string nState = "safe";
        
        float safeguard = 0;
                // For debugging purposes, tell the owner the result.
                llOwnerSay((string)Number);
                
                state wSafe;
            }
            
            // If the result is more than 600, make the object unsafe.
            else if(Number >= 600)
            {
            // Set the string so we know where we are.
        //string nState = "unsafe";
        float safeguard = 1;
                // Snitch about the number. Debugging.
                llOwnerSay((string)Number);
                
                state restart;
            }
            
            else
            {
            
                state restart;
            
            }
    
    
    }


            
}


// Restart a state.
state restart
{
    state_entry()
{
        if(safeguard == 0)
        {
            llOwnerSay("Safe reset!");
            state wSafe;
        }
        else if(safeguard == 1)
        {
            llOwnerSay("Unsafe reset!");
            state unsafe;
        }
    }
}

 

 

 

 

Link to comment
Share on other sites

Hi,

I have 2 suggestions...

1.   Why not just do a random number "coin flip"  any time an avatar is detected within 5 meters.......to decide if you need particles or not. (safe or unsafe)


2.   You will be able to write much simpler more efficient scripts..if you learn how to script without using state changes.

      You will be suprised at how much easier your scripts can be..  :)

 

Link to comment
Share on other sites

Like this for instance:

float timeLimit = 15; // Timer reset limit (in seconds). Default: 14400 (4 hours).integer safe;////////////////////////////Particle scripts!/////////////////////// SECTION ONE: APPEARANCE -- These settings affect how each particle LOOKS.integer      glow = TRUE;        // TRUE or FALSE(*)vector startColor = <1,0,0>;     // RGB color, black<0,0,0> to white<1,1,1>(*)vector   endColor = <1,0,0>;     //float  startAlpha = 1.0;         // 0.0 to 1.0(*), lower = more transparentfloat    endAlpha = 1.0;         //vector  startSize = <0.1,0.1,0>; // <0.04,0.04,0>(min) to <10,10,0>(max>, <1,1,0>(*)vector    endSize = <0.1,0.1,0>; // (Z part of vector is discarded)key     texture = "419c3949-3f56-6115-5f1c-1f3aa85a4606";          // Texture used for particles. Texture must be in prim's inventory.// SECTION TWO: FLOW -- These settings affect how Many, how Quickly, and for how Long particles are created.//     Note,integer count = 5;    // Number of particles created per burst, 1(*) to 4096float    rate = 0.1;   // Delay between bursts of new particles, 0.0 to 60, 0.1(*)float     age = 3.0;   // How long each particle lives, 0.1 to 60, 10.0(*)float    life = 2.0;   // When to stop creating new particles. never stops if 0.0(*)// SECTION THREE: PLACEMENT -- Where are new particles created, and what direction are they facing?float      radius = .30;      // 0.0(default) to 64?  Distance from Emitter where new particles are created.float  innerAngle = 0.75;  // "spread", for all ANGLE patterns, 0(default) to PIfloat  outerAngle = 0.0;        // "tilt", for ANGLE patterns,  0(default) to TWO_PI, can use PI_BY_TWO or PI as well.integer   pattern = PSYS_SRC_PATTERN_ANGLE_CONE; // Choose one of the following:// PSYS_SRC_PATTERN_EXPLODE (sends particles in all directions)// PSYS_SRC_PATTERN_DROP  (ignores minSpeed and maxSpeed.  Don't bother with count>1 )// PSYS_SRC_PATTERN_ANGLE_CONE (set innerangle/outerange to make rings/cones of particles)// PSYS_SRC_PATTERN_ANGLE (set innerangle/outerangle to make flat fanshapes of particles)vector      omega = <0,0,0>; // How much to rotate the emitter around the <X,Y,Z> axises. <0,0,0>(*)// Warning, there's no way to RESET the emitter direction once you use Omega!!// You must attach the script to a new prim to clear the effect of omega.// SECTION FOUR: MOVEMENT -- How do the particles move once they're created?integer followSource = FALSE;   // TRUE or FALSE(*), Particles move as the emitter moves, (TRUE disables radius!)integer    followVel = FALSE;    // TRUE or FALSE(*), Particles rotate towards their directioninteger         wind = FALSE;   // TRUE or FALSE(*), Particles get blown away by wind in the siminteger       bounce = FALSE;   // TRUE or FALSE(*), Make particles bounce on Z altitude of emitterfloat       minSpeed = 1.3;     // 0.01 to ? Min speed each particle is spit out at, 1.0(*)float       maxSpeed = 1.5;     // 0.01 to ? Max speed each particle is spit out at, 1.0(*)vector          push = <0,0,-0.6>; // Continuous force pushed on particles, use small settings for long lived particles//key           target = "";      // Select a target for particles to arrive at when they die// can be "self" (emitter), "owner" (you), "" or any prim/persons KEY.// Script variablesinteger flags;list sys;updateParticles(key target){    flags = 0;    if (target == "owner") target = llGetOwner();    if (target == "self") target = llGetKey();    if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK;    if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK;    if (startColor != endColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;    if (startSize != endSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK;    if (wind) flags = flags | PSYS_PART_WIND_MASK;    if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK;    if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK;    if (target != "") flags = flags | PSYS_PART_TARGET_POS_MASK;    sys = [  PSYS_PART_MAX_AGE,age,        PSYS_PART_FLAGS,flags,        PSYS_PART_START_COLOR, startColor,        PSYS_PART_END_COLOR, endColor,        PSYS_PART_START_SCALE,startSize,        PSYS_PART_END_SCALE,endSize,        PSYS_SRC_PATTERN, pattern,        PSYS_SRC_BURST_RATE,rate,        PSYS_SRC_ACCEL, push,        PSYS_SRC_BURST_PART_COUNT,count,        PSYS_SRC_BURST_RADIUS,radius,        PSYS_SRC_BURST_SPEED_MIN,minSpeed,        PSYS_SRC_BURST_SPEED_MAX,maxSpeed,        PSYS_SRC_TARGET_KEY,target,        PSYS_SRC_INNERANGLE,innerAngle,        PSYS_SRC_OUTERANGLE,outerAngle,        PSYS_SRC_OMEGA, omega,        PSYS_SRC_MAX_AGE, life,        PSYS_SRC_TEXTURE, texture,        PSYS_PART_START_ALPHA, startAlpha,        PSYS_PART_END_ALPHA, endAlpha            ];    float newrate = rate;    if (newrate == 0.0) newrate=.01;    if ( (age/rate)*count < 4096) llParticleSystem(sys);    else {        llInstantMessage(llGetOwner(),"Your particle system creates too many concurrent particles.");        llInstantMessage(llGetOwner(),"Reduce count or age, or increase rate.");        llParticleSystem( [ ] );    }}default {    state_entry() {        llSetTimerEvent(.1);    }        timer() {        llSetTimerEvent(timeLimit);        safe = TRUE;        if ((integer)llFrand(1000.0) > 500) safe = FALSE;        if (!safe) llSensorRepeat("","",AGENT_BY_LEGACY_NAME,5.0,PI,2.0);        else {
llSensorRemove();
llParticleSystem( [] );
} } sensor(integer total_number) { updateParticles( llDetectedKey(0) ); } no_sensor() { llParticleSystem( [ ] ); }}

 

  • Like 1
Link to comment
Share on other sites


dd Temin wrote:

Hi,

I have 2 suggestions...

1.   Why not just do a random number "coin flip"  any time an avatar is detected within 5 meters.......to decide if you need particles or not. (safe or unsafe)

 

2.   You will be able to write much simpler more efficient scripts..if you learn how to script without using state changes.

      You will be suprised at how much easier your scripts can be.. 
:)

 

Hi!

I need the particle spitter to consistently spit particles at everyone who comes within range for the 4 hours it's in "unsafe mode", so having it do a random coin flip ever time it detects an agent within range would defeat its purpose, really. I do agree I should learn how to script without using state changes as well. LSL is just a very difficult and cumbersome language to learn :<

Link to comment
Share on other sites

 

Ron Khondji wrote:

Like this for instance:

 

Edit: Scratch the below post. Turns out I just had to copy-paste it, delete it from the script & re-add it again.

 

Thank you for that, it looks much cleaner now! There's just one issue with it right now & that shows what I mean with how LSL is difficult & cumbersome to learn x3 There's a syntax error on line 105, but I can't see where it is because that line looks proper.

It involves this: if (!safe) llSensorRepeat("","",AGENT_BY_LEGACY_NAME,5.0,PI,2.0);

Link to comment
Share on other sites

Yeah, I'm sure. For some reason it was still giving me a syntax error, but I copied the same line which was giving the error, then deleted that one & pasted it in again, and that solved it.

 

This language is weird as heck >.> Or it might just be an undocumented bug in the compiler.

Link to comment
Share on other sites

Most likely just a bad cut & paste experience with a hidden character.  It happens.  LSL is no wierder than most computer languages.  I've forgotten most of the languages I've had to mess with in the past 45 years, but they all had quirks of one sort or another.  You just have to be patient and learn.

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4173 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...