Thursday, September 11, 2014

Fireflies [Level II]

In my early days in Second Life I picked up a free full-perm lightning bug script by Ama Omega; its name was Foxfire.

The script was set to turn fireflies on at sundown and off when the sun came back up. I managed to change that so they were active 24/7.

As fireflies go, Ama's weren't bad, but Sweetie (a recurring character in Chey's Second Life Blog)       wanted to tweak them. Fireflies she said, weren't yellow, but yellow-green. These didn't stay on quite long enough-- and they were too dense and not quite wide-ranging enough. And oh, yes, didn't fireflies come out only at night/ Why did these flash all day?

I had her apply color to a prim and, by doing some calculations, soon had the script making fireflies of the same shade. With Sweetie over my shoulder, I tweaked the script, making the flashes last a little longer, thinning the field of fireflies, and dispersing them over a wider range. Then I stayed online through a full four-hour Second Life day cycle and discovered just the right moment to turn them on (real life fireflies start just at dusk). Real life fireflies stop flashing after a few hours, but I conveniently ignored that fact of biology and turned them off when the sum was just above the horizon. Then we spent an evening walking around Whimsy finding the old fireflies and replacing them with the new ones. Using beacons made that relatively easy. Here's my post about the process.

Below you'll find my modified firefly script, and below that Ama's original Foxfire Script. Ama did a great job, but I think you'll find my tweaks make for a nicer effect.

You can drop the script into rocks, trees, or just about anywhere. Fireflies will come out as it begins to grow dark and disappear before it's fully light. Please note, The fireflies are responding to the Second Life day cycle on your sim, and not to your viewer setting of midday, morning, evening, or midnight.

Just cut and paste the code into a script in your prim and, voila! Fireflies!

// ----------------------

// Ama Omega's Foxfire script as modified by Cheyenne Palisades Under direction of Sweetie

//NOTES TO SELF ON TIME OF DAY
// sun z number gives its position in relation to the horizon
// if sun.z > 0, it is daytime
// Counts z down to night
// by z = .1 sun is low on horizon. Turn fireflies on
// if sun.z < 0, it is below the horizon
// z goes below 0 when sun reaches horizon
// by -.25 it is full dark
// At -.5 time begins to count down. Day counts up to 1.0, I think.


// 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 = TRUE;           // 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 = 0.8;                  // Life of each particle
float maxSpeed = 0;            // Max speed each particle is spit out at
float minSpeed = 0;            // Min speed each particle is spit out at
string texture;                 // Texture used for particles, default used if blank
float startAlpha = 0.1;           // Start alpha (transparency) value
float endAlpha = 1;           // End alpha (transparency) value
vector startColor = <.77, .985, .52>;    // Start color of particles <R,G,B>
vector endColor = <.77, .985, .52>;      // End color of particles <R,G,B> (if interpColor == TRUE)
vector startSize = <.3,.3,.3>;     // Start size of particles
vector endSize = <.1,.1,.1>;       // End size of particles (if interpSize == TRUE)
vector push = <0,0,0>;          // Force pushed on particles

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

// Script variables
integer flags;

updateParticles()
{
    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
{
    on_rez(integer start_param)
    {
        llResetScript();
    }
 
    state_entry()
    {
        llSetTimerEvent(10.0);
        llParticleSystem([]);
    }
 
timer()
    {
    vector sun = llGetSunDirection();
        if (sun.z > 0.09)
        {
            llParticleSystem([]);
        }
 
        else
        {
               updateParticles();
        }
    }
 
}

// ===========


Ama Omega's Original Foxfire script follows.

// ==============

// 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 = TRUE;           // 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;                  // Life of each particle
float maxSpeed = 0;            // Max speed each particle is spit out at
float minSpeed = 0;            // Min speed each particle is spit out at
string texture;                 // Texture used for particles, default used if blank
float startAlpha = 0.1;           // Start alpha (transparency) value
float endAlpha = 1;           // End alpha (transparency) value
vector startColor = <1,1,0>;    // Start color of particles <R,G,B>
vector endColor = <1,1,0>;      // End color of particles <R,G,B> (if interpColor == TRUE)
vector startSize = <.3,.3,.3>;     // Start size of particles 
vector endSize = <.1,.1,.1>;       // End size of particles (if interpSize == TRUE)
vector push = <0,0,0>;          // Force pushed on particles

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

// Script variables
integer flags;

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

//  ==================

4 comments:

  1. Oh these are lovely - thanks so much for posting

    ReplyDelete
  2. Can you show how to use an image as the particle in this code?

    >^..^<

    ReplyDelete
    Replies
    1. Replacing the line

      string texture; // Texture used for particles; default used if blank

      with

      string texture = "UUID you want to use" will technically do it, but the size and behavior of the particles would require you to tweak the start and end size of the particles. Good luck if you try it.

      Delete