Ordinal Christmas Particle Tree

// Christmas Particle Tree
// Ordinal Malaprop 2009-12-22

// LICENCE
// Creative Commons Attribution-Noncommercial 3.0
// See http://creativecommons.org/licenses/by-nc/3.0/ for more details

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

// Play with these values if you wish
float HEIGHT = 4.0;
float MAX_BEND = 0.05;
float BRANCH_LENGTH = 1.0;
integer BRANCH_DENSITY = 20;
vector BASE_COLOUR = <0.25, 0.75, 0.25>;

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

leaves(float z)
{
        z /= HEIGHT;
        llParticleSystem([
                PSYS_PART_FLAGS, PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_EMISSIVE_MASK,
                PSYS_PART_START_COLOR, BASE_COLOUR * ((z * 0.7) + llFrand(0.3)),
                PSYS_PART_START_ALPHA, 1.0,
                PSYS_PART_START_SCALE, <0.1, BRANCH_LENGTH, 0.0>,
                PSYS_PART_MAX_AGE, 30.0,
                PSYS_SRC_ACCEL, <0.00,0.00,0.0>,
                PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
                PSYS_SRC_ANGLE_BEGIN, PI * (0.5 + z * 0.4),
                PSYS_SRC_ANGLE_END, PI * (0.5 + z * 0.4),
                PSYS_SRC_BURST_RATE, 0.05,
                PSYS_SRC_BURST_PART_COUNT, BRANCH_DENSITY,
                PSYS_SRC_BURST_RADIUS, BRANCH_LENGTH * 0.62,
                PSYS_SRC_BURST_SPEED_MIN, 0.0,
                PSYS_SRC_BURST_SPEED_MAX, 0.05,
                PSYS_SRC_MAX_AGE, 0.0
        ]);
        llSleep(0.8);
        llParticleSystem([]);
}

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

default
{
        state_entry()
        {
                llSetAlpha(0.0, ALL_SIDES);
                llSetRot(ZERO_ROTATION);
                vector startPos = llGetPos();
                vector pos = startPos;
                pos.z += 1.0;
                rotation direction = llEuler2Rot(<0.0, 0.0, llFrand(TWO_PI)>);
                float bendiness = llFrand(MAX_BEND);
                llSetRot(direction);
                while (pos.z < startPos.z + HEIGHT) {
                        llSetPos(pos);
                        leaves(pos.z - startPos.z);
                        llSetRot(llEuler2Rot(<0.0, bendiness + llFrand(0.05), 0.0>)
                        * llGetRot());
                        pos += <0.0, 0.0, 0.5> * llGetRot();
                }
                llSetRot(ZERO_ROTATION);
                llSetPos(startPos);
                llSetAlpha(1.0, ALL_SIDES);
        }

        on_rez(integer p)
        {
                llResetScript();
        }

        touch_start(integer n)
        {
                llResetScript();
        }
}