Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Particle Script Simplifier

Norman Desmoulins
Grand Poohba
Join date: 10 Nov 2005
Posts: 194
08-17-2006 22:11
Personally, I like to work with particles in the simplest manner possible, just tweeking the parameters right at the function call, instead of a lot of variables.

Now and then I find a particle script that I like the basic functionality of, but want it in my own style... so I put together this script a while back, using bits & pieces from other scripts.

This isn't for the beginner...

CODE

//////////////////////////////////////////////////////////////////////////////////////////////////
// put your updateParticles here... modify it to return a list
//////////////////////////////////////////////////////////////////////////////////////////////////

// If you remove a particle script from an object, the object will continue
// To emit particles forever no matter what you do, unless you replace it with
// a new particle script or reset the particles

// Particles targetted to AV's will go right for the crotch, Particles love crotches.

// Vocabulary for Particles:
// Emitter = The object spitting out the particles
// Particles = The actual things being emitted
// Radius = The area particles can start within, Higher No. = Bigger Area
// Alpha = The Transparency value of the Particles
// Omega = The Spin of an emitter, or rather the stream of particles
// Comment = These things // are called commenting, anything after is read only
// = By humans and is not compiled by the system.

// PARTICLE BEHAVIOR - TRUE = ON, FALSE = OFF
// Change TRUE or FALSE only, and make sure to stay in CAPS, with a ; at the end

integer glow = FALSE; // Make the particles glow from inside
// if FALSE they will be effected by the local light.

integer bounce = FALSE; // Particles won't go lower than the emitter and will
//bounce on the "ground" level if negative push is applied.

integer interpColor = TRUE; // Changes from start to end color
// Start and End colors are set below

integer interpSize = TRUE; // Changes from start to end size
// Also Set below

integer wind = FALSE; // Particles effected by wind
// Particles REALLY effected, will fly like crazy

integer followSource = TRUE; // Particles follow the emitter, so they will move
// In direct lines even if emitter is in motion
// IF FALSE they will sway like smoke, leaving a trail

integer followVel = TRUE; // Particles will emit in direction object facing
// Use with ANGLE Patterns and negative push to create
// waterfalls, etc

// PARTICLE PATTERNS

// Choose a pattern from this list:
// Cut and Paste "PSYS_SRC_PATTERN_*" from the red list into the blue one, the blue
// One is the actively selected particle style

// PSYS_SRC_PATTERN_EXPLODE
// This one makes particles appear anywhere within the radius at random.

// PSYS_SRC_PATTERN_DROP
// This one makes particles appear as if dropping from a small hole in the emitter

// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// This one makes particles appear in the inverse of a cone, usually nothing.

// PSYS_SRC_PATTERN_ANGLE_CONE
// This one makes particles appear in a cone, like a flashlight beam.

// PSYS_SRC_PATTERN_ANGLE
// This one makes particles appear in a flat fan shape fanning out from emitter.

//THE LINE BELOW THIS IS WHERE YOU PASTE THE PARTICLE PATTERN
integer pattern = PSYS_SRC_PATTERN_ANGLE_CONE;

// PARTICLE TARGET

// For no Target, leave this alone as: key target = "";
// To target the emitters OWNER, simply put: key target = "owner";
// To target the emitter itself, simply put: key target = "self";
// or if targetting another piece of the linked object the link number is placed be
// low in another section, just leave this as: key target = "";
key target = "";

// PARTICLE SETTINGS
float age = 0.5; // How long each particle will survive

float maxSpeed = 6; // Max speed each particle is spit out at
float minSpeed = 2; // Min speed each particle is spit out at
// To create bursts of particles all sticking together
// Set both min and max speed to the same thing.

string texture; // Texture used for particles, default used if blank
// Type the name of the texture in the " ", Make sure
// To drag the Texture into the emitters contents.

float startAlpha = 0; // Start alpha (transparency) value
float endAlpha = 1; // End alpha (transparency) value
// Alpha is between 0.0 and 1.0

vector startColor = <1,1,1>; // Starting color of particles <R,G,B>
vector endColor = <1,1,1>; // End color of particles <R,G,B>
// <0,0,0> = Black <1,1,1> = White
// InterpColor (above) must be TRUE for color to change

vector startSize = <.1, .1, .1>; // Start size of particles
vector endSize = <.1, .1, .1>; // End size of particles (if interpSize == TRUE)
// Size Range is 0.01 to 7.00
// Further the 3rd number doesn't effect anything

vector push = <0,0,0>; // Force pushed on particles (X,Y,Z)
// X = East/West Y = North/South Z= Up/Down


// PARTICLE PARAMETERS
float rate = 0.1; // How many seconds between particle emissions
float radius = .0001; // Starting radius for Particles to appear within
integer count = 9999999; // How many particles per emission (Per Rate)


float outerAngle = 0; // Outer angle for all ANGLE patterns (for a stream 0.1)
float innerAngle = .4; // Inner angle for all ANGLE patterns (for a stream 0.0)
// In Radians, so every 1 is 90 degrees between 0 and 3

vector omega = <0,0,0>; // Rotation of ANGLE patterns (X,Y,Z axis (E/W,N/S,UP/DOWN)
// This rotates the spray in a circle, not the particles

float life = 0; // Time from Start to Stop to emit Particles

// Script variables
integer flags;

list updateParticles()
{
// PARTICLE TARGETTING WITHIN LINKED OBJECTS
// In an object composed of multiple prims they are assigned a specific number
// based on the order in which they were linked. Particles can be targetted to a
// specific link number by simply removing the // from the line below this
// paragraph and putting the link number in the ( )'s

//target = llGetLinkKey(0);

// eg.: target = llGetLinkKey(7);

// use the link-num identifier script to get an objects number, IM me for that
// script if you don't have one.



// // DO NOT CHANGE ANY OF THESE FLAGS, THE PARTICLES WILL NOT FUNCTION // //

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;

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

//////////////////////////////////////////////////////////////////////////////////////////////////

ShowParticles()
{
list sys = updateParticles();
llInstantMessage(llGetOwner(), ndList2String(sys));
llParticleSystem(sys);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

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 == "color") interpColor = type;
else if (v == "interpsize") interpSize = type;
else if (v == "size") interpSize = type;
else if (v == "wind") wind = type;
else if (v == "followsource") followSource = type;
else if (v == "source") followSource = type;
else if (v == "followvel") followVel = type;
else if (v == "velocity") followVel = type;
ShowParticles();
}

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") || (v == "CONE"))
pattern = PSYS_SRC_PATTERN_ANGLE_CONE;
else if (v == "ANGLE")
pattern = PSYS_SRC_PATTERN_ANGLE;
else return;
ShowParticles();
}

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

string AddFlag(string v, string f)
{
if (llStringLength(v) > 0) v = v+" | "+f;
else v = f;
return v;
}

string Flags2String(integer f)
{
string v = "";
if (f & PSYS_PART_BOUNCE_MASK) v = AddFlag(v, "PSYS_PART_BOUNCE_MASK");
if (f & PSYS_PART_EMISSIVE_MASK) v = AddFlag(v, "PSYS_PART_EMISSIVE_MASK");
if (f & PSYS_PART_FOLLOW_SRC_MASK) v = AddFlag(v, "PSYS_PART_FOLLOW_SRC_MASK");
if (f & PSYS_PART_FOLLOW_VELOCITY_MASK) v = AddFlag(v, "PSYS_PART_FOLLOW_VELOCITY_MASK");
if (f & PSYS_PART_INTERP_COLOR_MASK) v = AddFlag(v, "PSYS_PART_INTERP_COLOR_MASK");
if (f & PSYS_PART_INTERP_SCALE_MASK) v = AddFlag(v, "PSYS_PART_INTERP_SCALE_MASK");
if (f & PSYS_PART_TARGET_LINEAR_MASK ) v = AddFlag(v, "PSYS_PART_TARGET_LINEAR_MASK ");
if (f & PSYS_PART_TARGET_POS_MASK) v = AddFlag(v, "PSYS_PART_TARGET_POS_MASK");
if (f & PSYS_PART_WIND_MASK ) v = AddFlag(v, "PSYS_PART_WIND_MASK ");
return v;
}

string Pattern2String(integer p)
{
if (p==PSYS_SRC_PATTERN_ANGLE) return "PSYS_SRC_PATTERN_ANGLE";
if (p==PSYS_SRC_PATTERN_ANGLE_CONE) return "PSYS_SRC_PATTERN_ANGLE_CONE";
if (p==PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY) return "YS_SRC_PATTERN_ANGLE_CONE_EMPTY";
if (p==PSYS_SRC_PATTERN_DROP) return "PSYS_SRC_PATTERN_DROP";
if (p==PSYS_SRC_PATTERN_EXPLODE) return "PSYS_SRC_PATTERN_EXPLODE";
return (string)p;
}

dumpParams()
{
string v = "partList = [\n";

v += " PSYS_PART_FLAGS, " + Flags2String(flags) + ",\n";
v += " PSYS_PART_MAX_AGE, " + (string)age + ",\n";
v += " PSYS_PART_START_COLOR, " + (string)startColor + ",\n";
v += " PSYS_PART_END_COLOR, " + (string)endColor + ",\n";
v += " PSYS_PART_START_SCALE, " + (string)startSize + ",\n";
v += " PSYS_PART_END_SCALE, " + (string)endSize + ",\n";
v += " PSYS_PART_START_ALPHA, " + (string)startAlpha + ",\n";
v += " PSYS_PART_END_ALPHA, " + (string)endAlpha + ",\n";

v += " PSYS_SRC_PATTERN, " + Pattern2String(pattern) + ",\n";
v += " PSYS_SRC_BURST_RATE, " + (string)rate + ",\n";
v += " PSYS_SRC_ACCEL, " + (string)push + ",\n";
v += " PSYS_SRC_BURST_PART_COUNT, " + (string)count + ",\n";
v += " PSYS_SRC_BURST_RADIUS, " + (string)radius + ",\n";
v += " PSYS_SRC_BURST_SPEED_MIN, " + (string)minSpeed + ",\n";
v += " PSYS_SRC_BURST_SPEED_MAX, " + (string)maxSpeed + ",\n";
v += " PSYS_SRC_TARGET_KEY, " + (string)target + ",\n";
v += " PSYS_SRC_INNERANGLE, " + (string)innerAngle + ",\n";
v += " PSYS_SRC_OUTERANGLE, " + (string)outerAngle + ",\n";
v += " PSYS_SRC_OMEGA, " + (string)omega + ",\n";
v += " PSYS_SRC_MAX_AGE, " + (string)life + ",\n";
v += " PSYS_SRC_TEXTURE, \"" + (string)texture + "\"\n";

v += "];\n";

llInstantMessage(llGetOwner(), v);
}

string ndList2String(list l)
{
integer len = llGetListLength(l);
string csv = "";
integer i;
for (i = 0; i < len; ++i)
{
if (i > 0) csv += "|";
csv += (string)llGetListEntryType(l, i)+":"+(string)llList2List(l, i, i);
}
return csv;
}

dumpInv()
{
integer j = llGetInventoryNumber(INVENTORY_ALL);
integer i;
for (i = 0; i < j; i++)
{
string name = llGetInventoryName(INVENTORY_ALL, i);
integer type = llGetInventoryType(name);
if (type != INVENTORY_SCRIPT)
{
llInstantMessage(llGetOwner(),
name+" : "+
(string)llGetInventoryKey(name)+" : "+
(string)llGetInventoryType(name)+" : "+
(string)llGetInventoryPermMask(name, MASK_EVERYONE));
}
}
}

default
{
state_entry()
{
texture = llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, 0));
ShowParticles();
dumpInv();
dumpParams();
}

changed(integer changes)
{
if (changes & CHANGED_INVENTORY) llResetScript();
}
}
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Discussion Thread
08-18-2006 20:54
/54/0b/131079/1.html
_____________________
i've got nothing. ;)
Samantha Samiam
Registered User
Join date: 6 Sep 2004
Posts: 53
touch to start/stop?
09-02-2006 23:38
I have tweaked this enough to behappy witht he results and flexibility of the script, but I need it to stop and start with a touch script. I have tried splicing in parts of a script that do this, and it won't work, I get a syntax error, but it works in the original particle script.

Anyone have any idea how I would get this to stop or start (I don't really care which is the default state at this point) this script? I know it's simple, but I just can't fake my way through this one.