SpawnParticle (ZScript)

From ZDoom Wiki
Jump to navigation Jump to search
Note: This feature is for ZScript only.

struct LevelLocals
native void SpawnParticle(FSpawnParticleParams p);


Spawns a particle on the map. This acts as a struct-using replacement for A_SpawnParticleEx, due to how many parameters that method has. Since this method is in the LevelLocals struct, it must be called with the LevelLocals or Level prefix.


  • p: A pointer to the FSpawnParticleParams struct that stores the parameters the function will use.


Warning: The default values for the fields in a struct are the same as the default values of a variable upon declaration (so, for example, for integer fields the default value is 0, for double fields it's 0.0, etc.). As such, fields like startalpha and color1 do not have the same default values as the parameters of A_SpawnParticleEx and must be set to the necessary value explicitly!. For example, you must explicitly set startalpha to 1.0, otherwise the particle will be invisible

The parameters the FSpawnParticleParams struct has are the same as the ones A_SpawnParticleEx uses. However, several parameters are squashed into Vector3 parameters, and some are renamed:

  • int color1
This parameter is what 'color1' is renamed to. Color can be applied to textured particles as well, resulting in tinted textures.
Since this is an integer field, the default value for it is 0, which means black. If you want to use a textured particle and NOT apply colorization to it, you need to explicitly set color1 = "".
  • TextureID texture
The texture used by the particle, same as A_SpawnParticleEx. If omitted, default untextured particles will be used.
  • vector3 pos
The absolute XYZ coordinate to spawn the particle in. It replaces the relative x/y/zoff parameters that the other particle spawn methods have.
  • vector3 vel
The velocity to apply to the particle on the XYZ axes, like the velx/y/z parameters it replaces, these values are absolute as well.
  • vector3 accel
The acceleration to apply to the particle on the XYZ axes. It replaces the accelx/y/z parameters that the other particle spawn methods have.
  • int flags
  • SPF_FULLBRIGHT — Makes the particle full bright.
  • SPF_NOTIMEFREEZE — The spawned particle is not affected by the time freeze powerup or cheat.
  • SPF_REPLACE — If the the particle limit is reached, the oldest particles will be removed to make room for particles with SPF_REPLACE.
  • SPF_NO_XY_BILLBOARD - The particle does not have any sort of billboarding, causing it to render similarly to normal actor sprites, instead of facing the players' view at all times.
  • SPF_ROLL - allows the use of startroll, rollvel and rollaccel parameters.
  • SPF_LOCAL_ANIM — Spawns an animated particle whose animation runs independently of the games' timer. This means the graphics can be animated at different times, and that pausing the game also stops them from running. (New from 4.12.2)
  • int style
The render style of the particle. STYLE_Normal and STYLE_Translucent have the same effect.
For shaded render styles, the shading color is determined by the color1 parameter. Note that even without STYLE_Shaded, if color1 is not "", the particle will be shaded to that color.
  • int lifetime
The time in tics the particle will exist for.
  • double size
The size of the particle. Note that it's the absolute size in map units, and that, if the particle is textured, its texture will be scaled to this size. If you wish to apply scale in the same way you'd apply it to an actor (i.e. relative to the size of the graphic), you will first need to obtain the texture's size with TexMan.GetSize() and then multiply the result by the desired scale (such as 0.5 for 50% of the size), and use that value as size.
Note that particles are always round/square. As such, non-square textures will be stretched to fit.
  • double sizestep
By how much the size of the particle will change every tic. Negative values will make it smaller, positive values will make it bigger. Note, this isn't relative scale, this is absolute value, just like size.
  • double startalpha
This parameter is what 'startalphaf' is renamed to.
Since this is a double field, its default value is 0.0 Unless you explicitly set it to a higher value, your particle will spawn invisible!
  • double fadestep
Same as fadestepf in A_SpawnParticle: determines by how much the particle's alpha will be reduced every tic. If left unspecified, the particle will be fully opaque until it disappears. Set to -1 if you want to see gradual fadeout over its lifetime.
(New from 4.12) fadestep can also be negative: if the value is negative (but not -1 exactly), particles that are initially translucent can be faded in.
  • double startroll
The starting roll position of the particle in degrees. Requires the SPF_ROLL flag.
  • double rollvel
The particle's roll will change by this value every tick. Requires the SPF_ROLL flag.
  • double rollacc
The rollvel value will change by this value every tick (which allows you to increase or decrease the value by which the roll changes). Requires the SPF_ROLL flag.

The angle parameter does not exist in FSpawnParticleParams, since the SpawnParticle method uses absolute coordinates. This also means that the SPF_REL* flags do nothing by extension.


This simple actor uses textures particles to spawn textured particles (using the PLSSB0 sprite from the PlasmaBall) that move in a flame-like manner.

Note that it spawns 5 particles per tic using a FOR loop, and you can choose how much randomization you want to choosing what parts of the definition are inside the loop and which are outside.

class ParticlePlasmaFire : Actor
		radius 16;

	override void Tick()
		if (isFrozen())
		FSpawnParticleParams fp;
		fp.texture = TexMan.CheckForTexture('PLSSB0');
		fp.color1 = "";
		for (int i = 5; i > 0; i--)
			fp.lifetime = random[fp](40, 80);
			fp.pos.x = pos.x + frandom[fp](-radius, radius);
			fp.pos.y = pos.y + frandom[fp](-radius, radius);
			fp.pos.z = pos.z + frandom[fp](0, 16);
			fp.vel.xy = (frandom[fp](-2, 2), frandom[fp](-2, 2));
			fp.vel.z = frandom[fp](2, 4);
			fp.accel.xy = -(fp.vel.xy * 0.035); //acceleration is aimed to the opposite of velocity
			fp.accel.z = -(fp.vel.z / fp.lifetime);

			fp.size = random[fp](4, 10);
			fp.sizeStep = -(fp.size / fp.lifetime); //size reduces to 0 over lifetime
			fp.startalpha = frandom[fp](0.75, 1.0);
			fp.fadestep = -1;
			fp.startRoll = frandom[fp](0, 360);
			fp.rollvel = frandom[fp](-15, 15);
			fp.rollacc = -(fp.rollvel / fp.lifetime); //rollvel reduces to 0 over lifetime


This is a spawner that can be configured in a level editor to spawn different types of particles at a specified frequency:

class RandomParticleSpawner : Actor
		//$Title Random Particle Spawner
		//$Category Decoration
		//$Arg0 Particle Types
		//$Arg0Tooltip "What type of particle should the spawner create"
		//$Arg0Type 11
		//$Arg0Enum {0 = "Default"; 1 = "Fire Particles"; 2 = "Doomguy Hologram";}
		//$Arg1 Frequency
		//$Arg1Tooltip "How frequently (in tics) the spawner should create a particle"
		//$Arg1Default 35
	//Give some names to the possible values of Args[0]
	enum EParticleTypes
	Vector3 offsets; //The offsets relative to the spawner to use for each particle.
	override void Tick()
		//Spawn a particle every time that the age of the spawner can be divided by the spawn frequency. Or immediately spawn one if the frequency is 0 or less.
		if (args[1] <= 0 || GetAge() % args[1] == 0)
			//Play fire sound for fire particles.
			if (args[0] == TYPE_FIREBALL)
				A_StartSound ("vile/firecrkl",flags:CHANF_NOSTOP);
			//Stop fire sound if the particle type was changed during runtime.
				A_StopSound (CHAN_BODY);
			//Spawn boring default particle.
			if (args[0] == TYPE_DEFAULT)
				offsets = (FRandom (64,-64),FRandom (64,-64),0);
				FSpawnParticleParams DefaultParticle;
				DefaultParticle.Color1 = "Gray";
				DefaultParticle.Style = STYLE_None;
				DefaultParticle.Lifetime = 70;
				DefaultParticle.Pos = Vec3Offset (Offsets.X,Offsets.Y,Offsets.Z); //Spawn relative to the spawner.
				DefaultParticle.Size = 1.5;
				DefaultParticle.SizeStep = 1;
				DefaultParticle.Vel.Z = FRandom (0.2,6); //Randomize the velocity of the particle.
				DefaultParticle.StartAlpha = 1;
				DefaultParticle.FadeStep = 0.004;
				Level.SpawnParticle (DefaultParticle);
			//Spawn cool fire particle.
			else if (args[0] == TYPE_FIREBALL)
				offsets = (FRandom (64,-64),FRandom (64,-64),0);
				FSpawnParticleParams FireballParticle;
				FireballParticle.Texture = TexMan.CheckForTexture ("BAL1A0");
				FireballParticle.Color1 = "FFFFFF";
				FireballParticle.Style = STYLE_Add;
				FireballParticle.Flags = SPF_ROLL|SPF_FULLBRIGHT;
				FireballParticle.Vel = (FRandom (0.5,-0.5),FRandom (0.5,-0.5),FRandom (0.1,0.8)); //Randomize the velocity of the particle.
				FireballParticle.RollVel = 0.25;
				FireballParticle.StartAlpha = 1;
				FireballParticle.Size = 0.4;
				FireballParticle.SizeStep = 0.2;
				FireballParticle.Lifetime = FRandom (35,35*4); //Randomize the lifespan of the particle.
				FireballParticle.Pos = Vec3Offset (Offsets.X,Offsets.Y,Offsets.Z); //Spawn relative to the spawner.
				Level.SpawnParticle (FireballParticle);
				Level.SpawnParticle (FireballParticle); //Spawn more particles for better effect.
				Level.SpawnParticle (FireballParticle);
			//Spawn super cool Doomguy particle.
			else if (Args[0] == TYPE_DOOMGUY)
				FSpawnParticleParams DoomguyParticle;
				DoomguyParticle.Texture = TexMan.CheckForTexture ("PLAYA1");
				DoomguyParticle.Lifetime = INT.MAX; //Doom(guy) is eternal.
				DoomguyParticle.Style = STYLE_Add;
				DoomguyParticle.StartAlpha = 1;
				DoomguyParticle.FadeStep = -1;
				DoomguyParticle.Size = 75;
				DoomguyParticle.SizeStep = 0;
				DoomguyParticle.Color1 = "Blue";
				DoomguyParticle.Flags = SPF_FULLBRIGHT|SPF_REPLACE;
				DoomguyParticle.Pos = Self.Pos; //Spawn relative to the spawner.
				Level.SpawnParticle (DoomguyParticle);
			//If the spawner has no frequency, spawn only one particle and go away. Allows for spawning a single permanent Doomguy hologram for example.
			if (Args[1] <= 0)