EXPLOSIONS VFX

We'll use the most complex explosion script as an example since all parts usually used in explosions can be found in this script.

A good practice would be to have the Spg2\Scripts\ShipOnDestroy.sal opened up in Notepad++. Installing our N++ plugins is also advised as it is easier to read the script that way.

Only specific chunks of script code will be copied here to explain each segment. Script functions ARE NOT explained here. Review the Scripting section on each script function.

NOT all variables will be apparent in the copied chunks, but they are in the original script file!


THE THEORY BEHIND IT

Don't get intimidated by the size of the ShipOnDestroy script. It is not that complex. We're only repeating almost the same chunk several times to create a series of smaller explosions before the final bang.

In-game scripts are comprised of numerous individual parts:

  1. Texture-based explosion sprite animation
  2. Particle-based explosion (usually numerous instances)
  3. Debris-based explosions (created from models)
  4. Particle-based flash explosions that hide the removal of the exploding object

SIZE DEPENDENCY

To limit the number of almost identical scripts, the first part of the ShipOnDestroy.sal script sets some basic parameters regarding size of the exploding object.

	float radius = 0.0 ;
	ship GetParent GetRadius radius ;
	float sizeStart = 0.0 ;
	math sizeStart = radius / 8 ;
	float sizeEndInterm = 0.0 ;
	math sizeEndInterm = radius / 8 ;
	float sizeEnd = 0.0 ;
	math sizeEnd = sizeEndInterm + 0.5 ;
	float sizeSpark = 0.0 ;
	math sizeSpark = radius / 32 ;
	float sizeSparkFinal = 0.0 ;
	math sizeSparkFinal = radius / 3 ;
	float sizeDebris = 0.0 ;
	math sizeDebris = radius / 123 ;
	float sizeDebrisFinal = 0.0 ;
	math sizeDebrisFinal = radius / 37 ;
	

The code above sets the appropriate sizes of the explosion parts that can be scaled dynamically, via script functions.

	/* particle explosion IDs depending on ship size */
	int asbId = 39 ;
	int fogId = 68 ;
	int flashId = 30 ;
	int derChanceSize = 1 ;
	if radius > 0.01 && radius < 10.01
		math asbId = Rnd 36 38 ;
		fogId = 68 ;
		math flashId = Rnd 27 29 ;
		derChanceSize = 1 ;
	endif
	if radius > 10.01 && radius < 20.01
		math asbId = Rnd 39	41 ;
		fogId = 69 ;
		math flashId = Rnd 30 32 ;
		derChanceSize = 2 ;
	endif
	if radius > 20.01 && radius < 100.01
		math asbId = Rnd 42	44 ;
		fogId = 70 ;
		math flashId = Rnd 33 35 ;
		derChanceSize = 3 ;
	endif
	

The above code handles those parts of the explosion script that cannot be scaled dynamically. For such instances, we created several sizes to cover all bases. Once again we checked the radius of the exploding object and in regards to that, we set the appropriate free model Ids (check FreeModel.wds database for reference). We've also included some randomization of the particle effects so they aren't the same every time. And finally, we've also linked the chance for a derelict to appear directly to object size. Larger objects will have higher chance of spawning a derelict when they're destroyed. We only set the flag here and do the actual chance calculations further down the script.


INITIAL BLAST

The initial blast, the first explosion in the chain has more elements than the rest.

	/* -------- BLOCK 1 -------- */

	/* Explosion animation -> Explosion.wds */
	float delay = 0.0 ;
	float3 position = 0 0 0 ;
	float3 diagOffset = 0 0 0 ;
	float3 color = 1.0 1.0 1.0 ;
	float transparency = 0.05 ;
	int id = 34 ;
	int sizeSort = 0 ;
	float duration = 1.0 ;
	float rndOffset = 0.0 ;
	int blend = 1 ;

	math id = Rnd 34 37 ;
	ship GetParent GetRndPosition position ;
	explosion delay position diagOffset ... ;
	

This portion generates the texture-based explosion. These are simple series of sprites that together form a sprite animation.

	/* Fiery debris -> Debris.wds */
	int debrisId = 0 ;
	int number = 20 ;
	float shotTime = 0.2 ;
	float3 norm = 0 0 0 ;
	float arc = 0.0 ;
	float velMin = 15.0 ;
	float velMax = 16.0 ;
	float lifeMin = 1.0 ;
	float lifeMax = 1.5 ;
	int fadeSort = 0 ;

	fadeSort = 1 ;
	math debrisId = Rnd 0 6 ;
	math number = Rnd 10 30 ;
	debris delay debrisId number shotTime ... ;
	

This part of the code spawns fiery debris flying out fromt he center of explosion.

	/* Metal debris -> Debris.wds */
	fadeSort = 3 ;
	math debrisId = Rnd 7 11 ;
	math number = Rnd 10 20 ;
	debris delay debrisId number shotTime position ... ;
	

To improve the look and feel, we also added some metal debris that flies out from the explosion center.

	/* Particles -> FreeModel.wds */
	float lifetime = 1.0 ;
	assembly delay position asbId lifetime ;
	

This is the first instance of the particle explosion. This is one of those that cannot be scaled dynamically via script functions. It's lifetime should also correspond to the particle emitter lifetime so the emitter doesn't start respawning the explosion particles.

	/* sound */
	sound3d explosion1A position ;
	

What's an explosion without sound, right? This part handles the sound effect.


SERIES OF SIMILAR EXPLOSIONS FOLLOW

If you take a look further in the script, you'll see several more blocks. These are simply new instances of the above (but without the texture-based explosion). Between each block, we placed a short pause so it doesn't all explode at the same time.


FINAL BANG

	/* -------- FLASH FINAL & DELETE -------- */

	/* adjust flash position according to camera */
	float3 posCamera = 0 0 0 ;
	float3 e_posCC = 0 0 0 ;
	float3 posShip = 0 0 0 ;
	ship GetParent GetPosition posShip ;
	ship GetParent GetRadius shipSize ;

	camera VectorTo posCamera ;
	math e_posCC = posCamera * shipSize ;
	math posCamera = e_posCC * 0.6 ;
	math position = posShip + posCamera ;

	/* flashId particle set at the beginning of script */
	ship GetParent GetPosition position ;
	assembly delay position flashId lifetime ;
	/* fogId particle set at the beginning of script */
	float lifeFog = 5.0 ;
	assembly delay position fogId lifeFog ;

	/* sound */
	sound3d expl_big5 position ;

	...

	/* ship delete */
	float shipDelDelay = 0.5 ;
	ship GetParent Delete shipDelDelay ;
	

The final portion of the script handles how and when the exploding object will disappear. We use a simple approach of creating a flash particle placed between the exploding object and the camera to obscure the object at the time of its disappearance.


A BIT OF ADVICE

Perhaps a good advice to give at this time is that when handling explosions and removal of objects via explosions, feel free to reuse this or similar default scripts, or parts of it. And then, once you're more familiar with the whole structure and system, start creating your own customized explosion script. As always, if you get stuck or if you have questions, send us an email at modding at starpointgemini.com.