Particle System Tool

Expired

ParticleSystemToolThis object is a tool for helping Second Life users make scripted particle systems.  It includes a script:    ParticleSystemTool.lslwhich will make particle systems on command as well as change the particle system parameters in real-time.  Please read the comments inside the script for help on how to use it.  Also included are a collection of sample textures that work well for particle systems. 

 

// ParticleSystemTool.lsl
//
// There are four calls in the scripting language that produce
// particle-systems.  They are:
// 
//      llMakeExplosion()
//      llMakeFire()
//      llMakeFountain()
//      llMakeSmoke()
//
// Unfortunately, the documentation in the Second Life scripting
// guide is woefully inadequate.  What to do?  ==>  Experiment!
// 
// This script can help an intrepid scriptor home in on good
// parameters for making a particle-system look "just right".
// It accepts commands from its owner that can make any of the 
// four particle systems, or change the values of the parameters
// that are used in the llMake*() call.
// 
// To make a particle system, chat one of the following commands:
//
//      explosion   -- rapidly expanding, no fading
//      fire        -- rises quickly, fades quickly
//      fountain    -- bounces on some plane, influenced by wind
//      smoke       -- rises slow, fades slow
//
// To hear a report on the current values being used in the script
// call, chat the following command:
//
//      report      -- chats list of parameter values     
//
// To change one of the parameters, use a command of the form:
//
//      parameter,value
//
// Where "parameter" is one of the following:
//
//      count       -- the number of particles to produce (integer only)
//      scale       -- the size of particles
//      speed       -- speed at which particles move
//      lifetime    -- how long particles last
//      arc         -- arc of randomization
//      bounce      -- ??? (fountain only) (integer only)
//      offset      -- where to spawn the particles (in object's z direction)
//      bounce_offset   -- ??? (fountain only)
//
// and "value" is a number, whitespace is allowed after the comma
//
// Note: the same parameters passed to different varieties of particle
// systems will produce very different results.  For instance, since "fire"
// systems decay faster than "explosion" systems, the same "lifetime" 
// parameter will not produce particle systems with the same apparent
// lifetime.  Hence the need for this script for exploring what works,
// and what doesn't.
//
// Play and learn.
//
// Andrew Linden

  
// These are the parameters
integer count = 10;
float scale = 1.0;
float speed = 0.5;
float lifetime = 10.0;
float arc = PI;                     // radians (not solid-angle)
integer bounce = 1;                 // fountain only
vector offset = <0,0,1>;
float bounce_offset = 1.0;          // fountain only

string last_command = "fountain";

// change this line to change the texture used in the particle system
// (the texture must be in this object's inventory, and have the 
// exact name you supply here)
string particle_texture = "Jet Blast";


// a custom function for figuring out which particle system to make
make_particles(string command)
{
    // this script expects a texture in the object's inventory called "heart"
    if (command == "fountain")
        {
            llMakeFountain(count, scale, speed, lifetime, arc, bounce, particle_texture, offset, bounce_offset);
            last_command = command;
        }
        else if (command == "explosion")
        {
            llMakeExplosion(count, scale, speed, lifetime, arc, particle_texture, offset);
            last_command = command;
        }
        else if (command == "fire")
        {
            llMakeFire(count, scale, speed, lifetime, arc, particle_texture, offset);
            last_command = command;
        }
        else if (command == "smoke")
        {
            llMakeSmoke(count, scale, speed, lifetime, arc, particle_texture, offset);
            last_command = command;
        }
}


default
{
    state_entry()
    {
        // only accept commands from the owner
        llListen(0, "", llGetOwner(), "");
        last_command = "explosion";
    }
    
    touch_start(integer touch_count)
    {
        // make another particle system like the last one
        make_particles(last_command);
    }
    
    listen(integer channel, string name, key id, string command)
    {
        // convert the comma separated values (CSV) to a list
        list command_list = llCSV2List(command);
        integer list_length = llGetListLength(command_list);
        
        if (list_length == 1)
        {
            // found a single-word command
            if (command == "report")
            {
                llWhisper(0, "count = " + (string)count);
                llWhisper(0, "scale = " + (string)scale);
                llWhisper(0, "speed = " + (string)speed);
                llWhisper(0, "lifetime = " + (string)lifetime);
                llWhisper(0, "arc = " + (string)arc);
                llWhisper(0, "bounce = " + (string)bounce);
                llWhisper(0, "offset = " + (string)offset);
                llWhisper(0, "bounce_offset = " + (string)bounce_offset);
            }  
            else
            {
                make_particles(command);
            }
        }
        else if (list_length == 2)
        {
            // found a command of the form: "parameter,value"
            string variable = llList2String(command_list, 0);
            string value = llList2String(command_list, 1);
            if (variable == "count")
            {
                count = llList2Integer(command_list, 1);
                llWhisper(0, "count = " + (string)count);
            }
            else if (variable == "scale")
            {
                scale = llList2Float(command_list, 1);
                llWhisper(0, "scale = " + (string)scale);
            }
            else if (variable == "speed")
            {
                speed = llList2Float(command_list, 1);
                llWhisper(0, "speed = " + (string)speed);
            }
            else if (variable == "lifetime")
            {
                lifetime = llList2Float(command_list, 1);
                llWhisper(0, "lifetime = " + (string)lifetime);
            }
            else if (variable == "arc")
            {
                arc = llList2Float(command_list, 1);
                llWhisper(0, "arc = " + (string)arc);
            }
            else if (variable == "bounce")
            {
                bounce = llList2Integer(command_list, 1);
                llWhisper(0, "bounce = " + (string)bounce);
            }
            else if (variable == "offset")
            {
                // we can't pass vectors into a CSV, so we only change the z-value here
                offset.z = llList2Float(command_list, 1);
                llWhisper(0, "offset = " + (string)offset);
            }
            else if (variable == "bounce_offset")
            {
                bounce_offset = llList2Float(command_list, 1);
                llWhisper(0, "bounce_offset = " + (string)bounce_offset);
            }
        }
    }
}

 

Shower

Expired

// Particle Script 0.3
// Created by Ama Omega
// 10-10-2003

// Mask Flags - set to TRUE to enable
integer glow = TRUE;            // Make the particles glow
integer bounce = FALSE;          // Make particles bounce on Z plan of object
integer interpColor = TRUE;     // Go from start to end color
integer interpSize = TRUE;      // Go from start to end size
integer wind = FALSE;           // Particles effected by wind
integer followSource = FALSE;    // Particles follow the source
integer followVel = TRUE;       // Particles turn to velocity direction

// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_ANGLE_CONE;

// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner 
//    and "self" will target this object
//    or put the key of an object for particles to go to
key target = "";

// Particle paramaters
float age = 2.0;                  // Life of each particle
float maxSpeed = 2.0;            // Max speed each particle is spit out at
float minSpeed = 1.0;            // Min speed each particle is spit out at
string texture;                 // Texture used for particles, default used if blank
float startAlpha = 1;           // Start alpha (transparency) value
float endAlpha = 1;           // End alpha (transparency) value
vector startColor = <1 ,1,1>;    // Start color of particles 
vector endColor = <1 ,1,1>;      // End color of particles  (if interpColor == TRUE)
vector startSize = <0.02,0.1,0.02>;     // Start size of particles 
vector endSize = <0.04,0.1,0.04>;       // End size of particles (if interpSize == TRUE)
vector push = <0,0,0>;          // Force pushed on particles


// System paramaters
float rate = 0.2;            // How fast (rate) to emit particles
float radius = 0.01;          // Radius to emit particles for BURST pattern
integer count = 50;        // How many particles to emit per BURST 
float outerAngle = 3;    // Outer angle for all ANGLE patterns
float innerAngle = 0.9;    // Inner angle for all ANGLE patterns
float beginAngle = 0.2;    // Angle Begin for all ANGLE patterns
float endAngle = 0;    //Angle End for all ANGLE patterns

vector omega = <0,0,0>;    // Rotation of ANGLE patterns around the source
float life = 0;             // Life in seconds for the system to make particles

// Script variables
integer flags;

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 (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
    if (interpSize) 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;

    llParticleSystem([  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_ANGLE_BEGIN,beginAngle, 
                        PSYS_SRC_ANGLE_END,endAngle, 
                        PSYS_SRC_OMEGA, omega,
                        PSYS_SRC_MAX_AGE, life,
                        PSYS_SRC_TEXTURE, texture,
                        PSYS_PART_START_ALPHA, startAlpha,
                        PSYS_PART_END_ALPHA, endAlpha
                            ]);
}

default
{
    state_entry()
    {
        updateParticles();
    }
}

 

Candle Flame Script

Expired

// Particle Script 0.3
// Created by Ama Omega
// 10-10-2003

// Mask Flags - set to TRUE to enable
integer glow = TRUE;            // Make the particles glow
integer bounce = FALSE;          // Make particles bounce on Z plan of object
integer interpColor = TRUE;     // Go from start to end color
integer interpSize = TRUE;      // Go from start to end size
integer wind = FALSE;           // Particles effected by wind
integer followSource = FALSE;    // Particles follow the source
integer followVel = TRUE;       // Particles turn to velocity direction

// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY;

// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner 
//    and "self" will target this object
//    or put the key of an object for particles to go to
key target = "";

// Particle paramaters
float age = 0.4;                  // Life of each particle
float maxSpeed = 0.1;            // Max speed each particle is spit out at
float minSpeed = 0.1;            // Min speed each particle is spit out at
string texture;                 // Texture used for particles, default used if blank
float startAlpha = 1;           // Start alpha (transparency) value
float endAlpha = 0.0;           // End alpha (transparency) value
vector startColor = <1 ,0.5,0>;    // Start color of particles 
vector endColor = <1 ,1,0>;      // End color of particles  (if interpColor == TRUE)
vector startSize = <0.06,0.08,0.06>;     // Start size of particles 
vector endSize = <0.04,0.08,0.04>;       // End size of particles (if interpSize == TRUE)
vector push = <0,0,0.7>;          // Force pushed on particles


// System paramaters
float rate = 0.01;            // How fast (rate) to emit particles
float radius = 0.001;          // Radius to emit particles for BURST pattern
integer count = 100;        // How many particles to emit per BURST 
float outerAngle = 0.08;    // Outer angle for all ANGLE patterns
float innerAngle = 0.9;    // Inner angle for all ANGLE patterns
vector omega = <0,0,0>;    // Rotation of ANGLE patterns around the source
float life = 0;             // Life in seconds for the system to make particles

// Script variables
integer flags;

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 (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
    if (interpSize) 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;

    llParticleSystem([  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
                            ]);
}

default
{
    state_entry()
    {
        updateParticles();
    }
}

 

Bubble Blower

Expired

// Particle Script 0.3
// Created by Ama Omega
// 10-10-2003

// Mask Flags - set to TRUE to enable
integer glow = TRUE;            // Make the particles glow
integer bounce = FALSE;          // Make particles bounce on Z plan of object
integer interpColor = TRUE;     // Go from start to end color
integer interpSize = TRUE;      // Go from start to end size
integer wind = FALSE;           // Particles effected by wind
integer followSource = FALSE;    // Particles follow the source
integer followVel = TRUE;       // Particles turn to velocity direction

// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_ANGLE_CONE;

// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner 
//    and "self" will target this object
//    or put the key of an object for particles to go to
key target = "";

// Particle paramaters
float age = 5.0;                  // Life of each particle
float maxSpeed = 0.3;            // Max speed each particle is spit out at
float minSpeed = 0.03;            // Min speed each particle is spit out at
string texture = "Particle Texture - Bubble";                 // Texture used for particles, default used if blank
float startAlpha = 1;           // Start alpha (transparency) value
float endAlpha = 0;           // End alpha (transparency) value
vector startColor = <1 ,1,1>;    // Start color of particles 
vector endColor = <1 ,1,1>;      // End color of particles  (if interpColor == TRUE)
vector startSize = <0.05,0.05,0.05>;     // Start size of particles 
vector endSize = <0.05,0.05,0.05>;       // End size of particles (if interpSize == TRUE)
vector push = <0,0,0>;          // Force pushed on particles


// System paramaters
float rate = 5;            // How fast (rate) to emit particles
float radius = 0.03;          // Radius to emit particles for BURST pattern
integer count = 25;        // How many particles to emit per BURST 
float outerAngle = 3;    // Outer angle for all ANGLE patterns
float innerAngle = 0.9;    // Inner angle for all ANGLE patterns
float beginAngle = 0.4;    // Angle Begin for all ANGLE patterns
float endAngle = 0;    //Angle End for all ANGLE patterns

vector omega = <0,0,0>;    // Rotation of ANGLE patterns around the source
float life = 0;             // Life in seconds for the system to make particles

// Script variables
integer flags;

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 (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
    if (interpSize) 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;

    llParticleSystem([  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_ANGLE_BEGIN,beginAngle, 
                        PSYS_SRC_ANGLE_END,endAngle, 
                        PSYS_SRC_OMEGA, omega,
                        PSYS_SRC_MAX_AGE, life,
                        PSYS_SRC_TEXTURE, texture,
                        PSYS_PART_START_ALPHA, startAlpha,
                        PSYS_PART_END_ALPHA, endAlpha
                            ]);
}

integer channel = 22;

default
{
    state_entry()
    {
        updateParticles();
        llListen(channel, "", llGetOwner(), "");
    }

    listen(integer channel, string name, key id, string message)
    {
        if (message == "smoke hide")
        {
            llSetLinkAlpha( LINK_SET, 0, ALL_SIDES );
            llInstantMessage( llGetOwner(), "Smokey Feet hidden." );
                } else if (message == "smoke show") {
            llSetLinkAlpha( LINK_SET, 1, ALL_SIDES );
            llInstantMessage( llGetOwner(), "Smokey Feet shown." );
        }
    }
}