PDA

View Full Version : emitters


excaliber7388
06-25-2006, 06:43 PM
I've started working on a weather script, and I decided to use an emitter, to reduce lag. I've been reading the wiki, stefan's example, examples on here, and I can't figure out why this emitter isn't emitting:

with (findimg(200))
{
emitter.emit();
layer=2;
emitter.delaymin = .05;
emitter.delaymax = .05;
emitter.nofparticles = 20;
emitter.firstinfront = false;
emitter.particle.lifetime = 2;
emitter.particle.image = "dr-rain2.png";
emitter.particle.mode = 1;
emitter.particle.alpha = .8;
emitter.particle.zoom = random(.3,1);
emitter.particle.speed = 10;
emitter.particle.checkbelowterrain = true;
emitter.particle.movementvector=pi*.25;
x = player.x;
y = player.y;
}

If I don't ask, I don't learn, right? :\

ApothiX
06-26-2006, 02:15 AM
I've started working on a weather script, and I decided to use an emitter, to reduce lag. I've been reading the wiki, stefan's example, examples on here, and I can't figure out why this emitter isn't emitting:

with (findimg(200))
{
emitter.emit();
layer=2;
emitter.delaymin = .05;
emitter.delaymax = .05;
emitter.nofparticles = 20;
emitter.firstinfront = false;
emitter.particle.lifetime = 2;
emitter.particle.image = "dr-rain2.png";
emitter.particle.mode = 1;
emitter.particle.alpha = .8;
emitter.particle.zoom = random(.3,1);
emitter.particle.speed = 10;
emitter.particle.checkbelowterrain = true;
emitter.particle.movementvector=pi*.25;
x = player.x;
y = player.y;
}

If I don't ask, I don't learn, right? :\
If you set the delaymin and delaymax, I don't think you have to call .emit(), but if you do, you should be calling it after you set all the attributes, not before.

Yen
06-26-2006, 02:16 AM
You didn't define the emitter's red, blue, or green, so it's assuming they're all 0, which would cause it to not show.

excaliber7388
06-26-2006, 02:28 AM
hmm, I added emitter.particle.reb, blue, and green, got rid of the .emit(), and it still does nothing? :frown: srry

ApothiX
06-26-2006, 02:32 AM
Not sure but, you have no modifiers, telling it what to do after it's emitted. I'm not all that great with the particle emitter crap and I don't have NC on any servers at the moment, so I can't test it out :[

Yen
06-26-2006, 02:48 AM
Sorry, I missed this:
You have: emitter.nofparticles = 20;
The proper variable is 'nrofparticles'

I'm not sure if it assumes it to be 1 if it's not defined, but that may be your problem if it doesn't assume it to be 1.

excaliber7388
06-26-2006, 08:14 PM
Yay, now i have 1 raindrop....that stays still x_x
I can take the movement stuff off the wiki I suppose, but what would control the number of particls? I thought that was nrofparticles, but apparently not. I've changed the x and y to random variables. Still nothing.

_Z3phyr_
06-26-2006, 10:05 PM
To control the movement, you can:

use the zangle to make all particle movement upwards (set it to emitter.particle.zangle = 1; ) or downwards (-1).

use 'speed' to control the rate the particles move in whatever dir it is (emitter.particle.speed = x; at x tiles/second).



And there's other stuff too, but from what I was told Stefan made this weapon NPC so I'm sure it may help you. This code is for a falling leaves effect:


// Falling leaves

// Emitter attributes
layer = 2;
emitter.delaymin = 0.1;
emitter.delaymax = 0.3;
emitter.nrofparticles = 2;
emitter.emissionoffset = {0, -5, 10};
emitter.checkbelowterrain = true;

// Basic particle attributes
emitter.particle.lifetime = 10;
emitter.particle.image = "g4_particle_leaf.png";

// Movement
emitter.particle.zangle = -1;
emitter.particle.speed = 2;
emitter.particle.alpha = 0.75;
emitter.particle.mode = 1;

emitter.addglobalmodifier("impulse", 0.2, 0.2, "zangle", "multiply", 0.95, 0.95);
emitter.addlocalmodifier("once", 0, 0, "rotation", "replace", 0, 2*pi);
emitter.addlocalmodifier("once", 0, 0, "angle", "replace", degtorad(200), degtorad(260));
emitter.addlocalmodifier("once", 0, 0, "x", "add", -10, 25);
emitter.addlocalmodifier("once", 0, 0, "zoom", "replace", 0.6, 1.2);
emitter.addlocalmodifier("once", 0, 0, "green", "replace", 0.5, 1);
emitter.addglobalmodifier("impulse", 0.2, 0.2, "spin", "multiply", 0.6, 0.6);
emitter.addlocalmodifier("range", 0, 100000, "speed", "add", 3, 3);
with (emitter.addlocalmodifier("impulse", 1, 2, "spin", "add", -20, -30)) {
addmod("zangle", "add", 0.1, 0.5);
}

excaliber7388
06-27-2006, 06:00 AM
okay, I have rain! :D
But there's a few things I wonder if I can fix. First off, the rain stays in one place, it doesn't follow the player. And it seems to expance over a gmap, I'm not 100% sure if it stops, but I suppose it would :\

with (findimg(200))
{
layer=2;
emitter.delaymin = .05;
emitter.delaymax = .05;
emitter.nrofparticles = 25;
emitter.firstinfront = false;
emitter.particle.lifetime = 2;
emitter.particle.image = "dr-rain2.png";
emitter.particle.mode = 0;
emitter.particle.alpha = .8;
emitter.particle.zoom = random(.3,1);
emitter.particle.speed = 3;
emitter.particle.checkbelowterrain = true;
emitter.particle.movementvector=pi*.25;
emitter.particle.x = player.x;
emitter.particle.y = player.y;
emitter.particle.red = 1;
emitter.particle.green = 1;
emitter.particle.blue = 1;
emitter.addlocalmodifier("impulse", 0, 0, "x", "add", -2, 2);
emitter.addlocalmodifier("impulse", 0, 0, "y", "add", -2, 2);
}

ApothiX
06-27-2006, 08:02 AM
you'd want to set attachtoowner=true, and/or attachposition=true to make it follow the player. And yeah, those are the modifiers I was refering to in the earlier post.

Yen
06-27-2006, 07:49 PM
Or you could put it on the screen (layer >= 4)

ForgottenLegacy
07-06-2006, 06:15 AM
First off, Particle Emitters, or 'emitters' for short, are an extra segment of GraalScript2 added to v4. An emitter is an object within the TShowImg, or an image shown by a showimg() function. To understand emitters, one must understand first off what parts of an image we would need to alter, as well as some of the functions and commands one should know beforehand. Please note that one should not try to create an emitter without at least having some previous knowledge of basic GraalScript2

Primarily, the function 'findimg()' is used very, very often when creating emitters. This function works just like 'findplayer()' or 'findnpc()', as in, it returns the reference to an object. 'Findimg()' is used clientside with the emitters. Here is an example of code using 'findimg()':

//#CLIENTSIDE
function onCreated() {
showimg(1,"block.png",player.x,player.y);
with (findimg(1)) {
image = "light2.png";
x = player.x - 3;
y = player.y - 3;
alpha = .9;
}
}

This script would show 'block.png' at the player's location, then change the image to 'light2.png', move the image three tiles up and left, and change the alpha to .9. 'Findimg()' is very, very handy.

Secondly, an image not shown has an x and y value identical to the player's. For example:

//#CLIENTSIDE
function onCreated() {
player.chat = findimg(1).x;
}

Would set the player's chat to the x value of the current player, as image 1 was not defined in that script. Also, for an undefined image, the 'image' attribute is "", or an empty string.

And third, you do not need to define the image with 'showimg()' in order to cast an emitter on it. Most emitters I make are targeting images that have not been defined with script, unless, for instance, I'm making a cauldron NPC, which then would need the cauldron image to show.

Now, I will teach the emitters from start to finish, minus a small handful of details which I, myself, still don't understand.

A particle emitter is an object. Just like 'player.' or 'this.', it is an object. It's parent is the TShowImg, which is the showimg object. First off, you do not need to define an image to cast an emitter on it. in fact, I did not and I made some pretty nice and simple emitters. Now, the 'emitter.' object is how we access and create an emitter. First off, the basics:


//#CLIENTSIDE
function onCreated() {
with (findimg(#)) { // Replace # with the index of the image you want to modify. For some reason, emitters are still shown only to the current player, even when the index is less than 200. Wierd.
layer = 1; // This will make the emitter draw under the player
x = player.x;
y = player.y; // These will show the emitter at the player's coords.


Follow along with what I'm doing? Now, here are the variables we will need to define, after setting the layer, x, and y, and inside the findimg() bracket:


emitter.attachposition = boolean; // If the image's x and y move, would the entire emitter, every single particle at once, move along with the image? If true, every sprite moves when the image movies. If false, then only the point of origin, where the particles are created, move when the image is moved.
emitter.delaymin = float; // This is the minimum delay between emissions.
emitter.delaymax = float; // This is the maximum delay between emissions, both of these are in seconds.
emitter.emissionoffset = string; // In format of "{float, float, float}", it's the offset from the x, y, and z that an emission will show. It's the delta variables for the location, basically.
emitter.firstinfront = boolean; // Should the first emitted particle be in front of every other particle?
emitter.nrofparticles = integer; // The number of particles to be released at the same exact time when the emitter emits. For example, set this to two, and you'll have two particles released every time instead of the default 1.
emitter.maxparticles = integer; // The maximum number of particles that can exist at one time. If this limit is reached, the script will wait until one of the particles runs out before emitting another one.


There. Define those as you wish. Now, time to teach how to change the particle attributes, and not the laws that govern just the emitter itself.


emitter.particle.lifetime = float; // How long, in seconds, the emitter lasts.
emitter.particle.checkbelowterrain = boolean; // If true and if a particle's height (z) value falls below the current terrain height, 0 for non-gmaps or flat terrain, the particle would be destroyed.
emitter.particle.clippingbox = string; // In the format of {x1, y1, z1, x2, y2, z2}, particles that escape this box will be destroyed.
emitter.particle.image = string; // The imagename of the emitter
emitter.particle.mode = integer; // Either 0, 1, or 2, the same as changeimgmode. 0 = add, 1 = trans, 2 = subtract. Use this for a blacklight effect if you wish.
emitter.particle.alpha = float; // Between 0 and 1, the alpha colour for transparancy
emitter.particle.zoom = float; // The zoom effect of the particle
emitter.particle.red = float;
emitter.particle.green = float;
emitter.particle.blue = float; // These are between 0 and 1, and they're the colours of the individual particles
emitter.particle.zangle = float; // Between 0 and pi*2, it's the upward angle of the particles. Remember zangle from the shoot() function? Same idea.
emitter.particle.angle = float; // Again, between 0 and pi*2, it's the angle that the particle should flow.
emitter.particle.speed = float; // I'm not sure if this is measured in Tiles per second or what, but it's the speed. Higher = faster, obviously
emitter.particle.spin = float; // The number of times each particle rotates while it's being shown. Ex, 1 will make the particle rotate just once before it hides.
emitter.particle.stretchx = float; // This is how 'stretched' each particle will be, relative to width.
emitter.particle.stretchy = float; // This is how 'stretched' each particle will be, relative to height.



Now, emitters have something called 'modifiers' that, well, modify the emitter, basically. This is where my knowledge is slightly vague, as there are three types of modifiers, and I only understand one of them, so I will only teach one of them. The syntax for a modifier is as follows:


emitter.addLocalModifier(selection_type, range_min, range_max, modified_attrib, process, new_min, new_max);


Yeah, I know that looks daunting, but you handled the 'shoot()' function, right? So this shouldn't be as hard. Now. 'selection_type' is how the emitter knows what to modify. For example, if you say "once", the emitter will modify the particles only once. However, when you say "range", the emitter will keep modifying the particles while their lifetime is between 'range_min' and 'range_max'. 'modified_attrib' is the name of the particle attribute you want to modify. I've used "x", "y", "alpha", "zoom", "red", "green", "blue", "angle", "speed", "stretchx" and "stretchy". Lastly, 'process' is the mathematical way that the particles will be modified. I always use either "add" or "replace", but I know "multiply" exists as well. If you use "replace", with "range" as the 'selection_type', the the 'modified_attrib' attribute of the particles with the current lifetime between 'range_min' and 'range_max' will fade from 'new_min' to 'new_max'

For example, if I set the 'lifetime' to 3, and do this

emitter.addLocalModifier("range", 0, 3, "alpha", "replace", 1, 0);

Then the particles will start out with an 'alpha' value of 1, then fade to 0, arriving at 0 just as their lifetime ends. If you use "add" or "multiply" for the 'process', then the attribute you have for 'modified_attrib' will either be added to or multiplied by a random number between 'new_min' and 'new_max'. There are two more modifiers that exist


emitter.addEmitModifier(selection_type, range_min, range_max, modified_attrib, process, new_min, new_max);
emitter.addGlobalModifier(selection_type, range_min, range_max, modified_attrib, process, new_min, new_max);


Same basic story as above, but 'addEmitModifier()' modifies based on gravity or impulse, and 'addGlobalModifier()' is based on modifing every single particle at once, instead of one at a time or individually. So, for example, you could have every single particle fade at the exact same time in the exact same way with 'addGlobalModifier()' (And no, I haven't fiddled with these yet)

Just fiddle around with emitters, and you should get the hang of it. There's one last function I'd like to teach first


emitter.emit();


This forces the emitter to, basically, emit. Now, if you want to make an emitter emit only once, and not constantly, you'd set the 'delaymin' and 'delaymax' to 10000 (this is the number Stefan uses), then call an 'emit()' function after you set all the attributes of the emitter. Don't forget to hide the image with 'hideimg()', otherwise the thing will unexpectedly emit 10000 seconds later! (Note, I have yet to actually wait this long, so I have no clue if my last statement was correct or not. It would make sense if it was. z-z)

Now, if you understood all that, you should know as much about emitters as I do. So, go off onto your local GS2 server with your new, shiny VIP account and script up a storm! Note, you can put emitters in a weapon NPC (NPCw) or a level NPC. It doesn't matter, as long as it's clientside. So now, I hope you can use emitters for effects, ranging from weather systems to pick axes, crafting hammers, warp rings, fun effects scripts, and about anything else you can imagine. In my private hangout level, I have emitters to mimic the burning of incence, which looks rather nice.

ForgottenLegacy
07-06-2006, 06:17 AM
That post is at the exact message limit x_x

Anyway, I wrote that docu a long while back, and it should help. It gives an entire tutorial about emitters. Stefan's official docu about emitters was, in part, taken from my docu, so I think this should help. Contact me on aim at TheOneGC is you have any questions.