Particle Writer

Written by Kitsune

// Particle Script 0.3
// Created by Ama Omega
// 10-10-2003
// Interactive Dev Kit version by Cienna Rand
integer lHandle = -1;
integer run = 1;

// Mask Flags - set to TRUE to enable
integer glow = TRUE;
integer bounce = FALSE;
integer interpColor = TRUE;
integer interpSize = TRUE;
integer wind = FALSE;
integer followSource = FALSE;
integer followVel = TRUE;
integer pattern = 4;
key target = "";
float age = 5;
float maxSpeed = 0;
float minSpeed = 0;
string texture;
float startAlpha = 1;
float endAlpha = 0.1;
vector startColor = <1,0,1>;
vector endColor = <0,0,1>;
vector startSize = <0.1,0.1,0.1>;
vector endSize = <0.1,0.1,0.1>;
vector push = <0,0,1>;

float rate = 0.1;
float radius = 1;
integer count = 3;
float outerAngle = 0;
float innerAngle = 0;
vector omega = <0,0,20>;
float life = 0;

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

processFlag(string var)
{
    integer type;
    string c = llGetSubString(var, 0, 0);
    if (c == "+") type = TRUE;
    else if (c == "-") type = FALSE;
    else return;
    string v = llToLower(llGetSubString(var, 1, llStringLength(var)));
    if (v == "glow") glow = type;
    else if (v == "bounce") bounce = type;
    else if (v == "interpcolor") interpColor = type;
    else if (v == "interpsize") interpSize = type;
    else if (v == "wind") wind = type;
    else if (v == "followsource") followSource = type;
    else if (v == "followvel") followVel = type;
    updateParticles();
}

processPattern(string var)
{
    string v = llToUpper(var);
    if (v == "EXPLODE")
     pattern = PSYS_SRC_PATTERN_EXPLODE;
    else if (v == "DROP")
     pattern = PSYS_SRC_PATTERN_DROP;
    else if (v == "ANGLE_CONE_EMPTY")
     pattern = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY;
    else if (v == "ANGLE_CONE")
     pattern = PSYS_SRC_PATTERN_ANGLE_CONE;
    else if (v == "ANGLE")
     pattern = PSYS_SRC_PATTERN_ANGLE;
    else return;
    updateParticles();
}

showSetFlags()
{
    list f = [];
    if (glow) f += ["GLOW"];
    if (bounce) f += ["BOUNCE"];
    if (interpColor) f += ["INTERP_COLOR"];
    if (interpSize) f += ["INTERP_SIZE"];
    if (wind) f += ["WIND"];
    if (followSource) f += ["FOLLOW_SOURCE"];
    if (followVel) f += ["FOLLOW_VEL"];
    llWhisper(0, "Set: " + llList2CSV(f));
}

showPattern()
{
    if (pattern == PSYS_SRC_PATTERN_EXPLODE)
        llWhisper(0, "Pattern: EXPLODE");
    else if (pattern == PSYS_SRC_PATTERN_DROP)
        llWhisper(0, "Pattern: DROP");
    else if (pattern == PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY)
        llWhisper(0, "Pattern: ANGLE_CONE_EMPTY");
    else if (pattern == PSYS_SRC_PATTERN_ANGLE_CONE)
        llWhisper(0, "Pattern: ANGLE_CONE");
    else if (pattern == PSYS_SRC_PATTERN_ANGLE)
        llWhisper(0, "Pattern: ANGLE");
}

vector string2vector(string s)
{
    list foo = llCSV2List(s);
    vector v;
    v.x = llList2Float(foo,0);
    v.y = llList2Float(foo,1);
    v.z = llList2Float(foo,2);
    return v;
}

float fixColor(integer c)
{
    if (c > 255) return 255;
    if (c <= 0) return 0;
    return (float)c/255;
}

vector colorVector(string s)
{
    list foo = llCSV2List(s);
    vector v;
    v.x = fixColor(llList2Integer(foo,0));
    v.y = fixColor(llList2Integer(foo,1));
    v.z = fixColor(llList2Integer(foo,2));
    //llWhisper(0, "Debug: v: " + (string)v);
    return v;
}

dumpParams()
{
    llWhisper(0, "PART_MAX_AGE:" + (string)age);
    llWhisper(0, "PART_FLAGS:" + (string)flags);
    llWhisper(0, "PART_START_COLOR:" + (string)startColor);
    llWhisper(0, "PART_END_COLOR:" + (string)endColor);
    llWhisper(0, "PART_START_SCALE:" + (string)startSize);
    llWhisper(0, "PART_END_SCALE:" + (string)endSize);
    llWhisper(0, "SRC_PATTERN:" + (string)pattern);
    llWhisper(0, "SRC_BURST_RATE:" + (string)rate);
    llWhisper(0, "SRC_ACCEL:" + (string)push);
    llWhisper(0, "SRC_BURST_PART_COUNT:" + (string)count);
    llWhisper(0, "SRC_BURST_RADIUS:" + (string)radius);
    llWhisper(0, "SRC_BURST_SPEED_MIN:" + (string)minSpeed);
    llWhisper(0, "SRC_BURST_SPEED_MAX:" + (string)maxSpeed);
    llWhisper(0, "SRC_TARGET_KEY:" + (string)target);
    llWhisper(0, "SRC_INNERANGLE:" + (string)innerAngle);
    llWhisper(0, "SRC_OUTERANGLE:" + (string)outerAngle);
    llWhisper(0, "SRC_OMEGA:" + (string)omega);
    llWhisper(0, "SRC_MAX_AGE:" + (string)life);
    llWhisper(0, "SRC_TEXTURE:" + (string)texture);
    llWhisper(0, "PART_START_ALPHA:" + (string)startAlpha);
    llWhisper(0, "PART_END_ALPHA:" + (string)endAlpha);
}

default
{
    state_entry()
    {
        if (lHandle == -1) lHandle = llListen(0, "", llGetOwner(), "");
        else {
            llListenRemove(lHandle);
            lHandle = llListen(0, "", llGetOwner(), "");
        }
        updateParticles();
    }

    touch(integer num_deteced)
    {
        if (run == 1) {
            run *= -1;
            llParticleSystem([]);
        } else {
            run *= -1;
            updateParticles();
        }
    }
    
    listen(integer channel, string name, key id, string msg)
    {
        list argv = llParseString2List(msg, [" "], []);
        integer argc = llGetListLength(argv);
        string cmd = llToLower(llList2String(argv, 0));
        if (cmd == "set")
        {
            if (argc == 1) showSetFlags();
            else processFlag(llList2String(argv, 1));
        }
        else if (cmd == "pattern")
        {
            if (argc == 1) showPattern();
            else processPattern(llList2String(argv, 1));
        }
        else if (cmd == "target")
        {
            target = llList2String(argv, 1);
            if (target == "none") target = "";
                updateParticles();
        }
        else if (cmd == "age")
        {
            age = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "maxspeed")
        {
            maxSpeed = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "minspeed")
        {
            minSpeed = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "startalpha")
        {
            startAlpha = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "endalpha")
        {
            endAlpha = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "startcolor")
        {
            startColor = colorVector(llList2String(argv, 1));
            updateParticles();
        }
        else if (cmd == "endcolor")
        {
            endColor = colorVector(llList2String(argv, 1));
            updateParticles();
        }
        else if (cmd == "startsize")
        {
            startSize = string2vector(llList2String(argv, 1));
            updateParticles();
        }
        else if (cmd == "endsize")
        {
            endSize = string2vector(llList2String(argv, 1));
            updateParticles();
        }
        else if (cmd == "push")
        {
            push = string2vector(llList2String(argv, 1));
            updateParticles();
        }
        else if (cmd == "omega")
        {
            omega = string2vector(llList2String(argv, 1));
            updateParticles();
        }
        else if (cmd == "rate")
        {
            rate = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "radius")
        {
            radius = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "count")
        {
            count = llList2Integer(argv, 1);
            updateParticles();
        }
        else if (cmd == "outerangle")
        {
            outerAngle = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "innerangle")
        {
            innerAngle = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "life")
        {
            life = llList2Float(argv, 1);
            updateParticles();
        }
        else if (cmd == "on")
        {
            updateParticles();
        }
        else if (cmd == "off")
        {
            llParticleSystem([]);
        }
        else if (cmd == "dump")
        {
            dumpParams();
        }
    }
}