I modified a fireball projectile I made a few months ago to create sub-explosions and I ran numerous tests on the thing, I'd like to share my findings to help you guys implement some of your own sub-explosions. They can be very, very pretty. Also the fireball script is included in the second post along with some pictures for your enjoyment.
This is a rather long report and side tutorial, as per usual I've gone a bit overboard, so please feel free to skip to any section you might be having difficulties with. If you have any questions at all don't be afraid to ask
Sub-explosions are created from a main, Parent or Mother explosion. The sub-explosions are sometimes referred to daughters. You can issue a maximum of 5 direct sub explosions from any other explosion. The notation is:
datablock ExplosionData(ParentExplosion)
{
...
subExplosion[0] = DaughterExplosion1;
subExplosion[1] = DaughterExplosion2;
subExplosion[2] = DaughterExplosion3;
subExplosion[3] = DaughterExplosion4;
subExplosion[4] = DaughterExplosion5;
...
};
You are not limited to making 5 completely different sub-explosions, you may also refer a single explosion several times as a sub explosion:
datablock ExplosionData(ParentExplosion)
{
...
subExplosion[0] = DaughterExplosion1;
subExplosion[1] = DaughterExplosion1;
subExplosion[2] = DaughterExplosion1;
subExplosion[3] = DaughterExplosion2;
subExplosion[4] = DaughterExplosion2;
...
};
Keep in mind, sub-explosions are Regular Explosions, taken from any explosionData datablocks. More or less if you create the explosion from, say, a projectile it will be identical to an explosion created from another explosion. The only difference is sub-explosions do not exhibit any radius damage or radius impulse. They are purely for show.
The common issue: Why they don't work half the time or at all
Sub-explosions are very finicky things, especially with timing. Here are the two universal sub-explosion rules:
Rule 1 - A sub-explosion will only be created if it's Final calculated delay (delayMS +/- delayVariance) lies within the parent explosion's lifetime range.
Rule 2 - A sub-explosion will only be created if it's own lifetimeMS is LARGER then it's delayMS
So what is rule 2 telling us? Quite simply, it's saying that all sub-explosions' lifetimes begin as soon as the parent is created. However, the misconception that comes with this is then that people will then think the sub-explosions need to have a lifetime equal or less then the parent's to work, this however is not true. Some examples,
This sub-explosion does NOT work, it breaks both rules
Parent explosion: Lasts 600 milliseconds (MS)
Sub-explosion: Delayed by 1000 MS, lifetimeMS is 700 (In reality, the effects would last -300 MS, impossible)
This sub-explosion does NOT work, it breaks rule 1
Parent explosion: Lasts 600 milliseconds (MS)
Sub-explosion: Delayed by 1000 MS, lifetimeMS is 1200 (In reality, the effects would last 200 MS)
This sub-explosion does NOT work, it breaks rule 2
Parent explosion: Lasts 1100 milliseconds (MS)
Sub-explosion: Delayed by 1000 MS, lifetimeMS is 700 (In reality, the effects would last -300 MS, impossible)
This sub-explosion does work
Parent explosion: lifetimeMS is 600 milliseconds (MS)
Sub-explosion: Delayed by 500 MS, lifetimeMS is 700 (In reality, the effects would last 200 MS)
This sub-explosion also works
Parent explosion: lifetimeMS is 500 milliseconds (MS)
Sub-explosion: Delayed by 500 MS, lifetimeMS is 700 (In reality, the effects would last 200 MS)
So in summary, make sure the sub-explosion's delay is lower or equal to both the Parent's lifetime and the sub-Explosion's lifetime. Follow these rules and your sub explosions will work without fail.
On a side note, a weird exception I came accross:
This sub-explosion also works (even though it breaks the first rule)
Parent explosion: lifetimeMS is 450 milliseconds (MS)
Sub-explosion: Delayed by 500 MS, lifetimeMS is 700 (In reality, the effects would last 200 MS)
I have conducted a few range tests on the oddball example to try to find out what the minimum delay range needs to be from the Parent's lifetime to create the Sub-Explosion, so far I haven't come to any conclusion, other then when the difference is around 200 the example no longer creates a Sub-Explosion. So maybe rule 1 and 2 are linked, but it would require some more tests and it gets too complicated for what you guys will ever need. Anyhow,
Chain Reactions, linking sub explosions to even more sub explosions
I know what you guys are thinking now, probably along the lines of "Oh wow are you serious?". Yes, it is possible to assign yet another set of Sub-Explosions to other Sub-Explosions. The notation is the same as you will see,
datablock ExplosionData(DaughterExplosion1)
{
...
subExplosion[0] = DaughtersSubExplosion1;
subExplosion[1] = DaughtersSubExplosion2;
subExplosion[2] = DaughtersSubExplosion3;
subExplosion[3] = DaughterExplosion2; //And for good measure you may also refer explosions from the Parent explosion
subExplosion[4] = DaughterExplosion2;
...
};
These things multiply fast, if we have 5 Sub-Explosions from a main explosion, each off shooting into 5 other explosions, the grand total comes to 26 explosions (counting the initial parent).
Keep in mind, every sub explosion abides by Rules 1 and 2, as you go further down the chain it adds the limitations of the sub-explosion beforehand as well as the limitations of the main Parent that created the mess. Essentially,
Parent Explosion -> Sub-Explosion (Rule 1 and 2 for itself and Parent) -> Sub Sub-explosion (Rule 1 and 2 for itself, Sub-Explosion and Parent) -> and so on
You will probably never need to keep track of more then 2 sets of sub explosions, the first set is more then enough for a nice bang. The second is used if you want a really big complicated boom. It's not all that difficult to keep track either for that matter.
Some important Sub-Explosion functions
There are some functions provided within the explosionData datablock which can help in whatever you're trying to make with sub-explosions. Recall sub-explosions don't have their own datablock, they're explosionData types just like their parent explosion.
delayMS = ##;
The time delay in milliseconds until the sub explosion is created, or appears.
delayVariance = ##;
This varies the delay by adding or subtracting from it. The amount it adds or subtracts lies within the range from 0 to the value ## of the variance.
offset = #.##;
Determines the offset amount that this explosion will appear from the origin (works on both parent and referred sub-explosions). 0.5 is the horizontal length of a single brick stud.
An important note is that explosions using offset will not appear on the other side of any raycast-collision checking wall or terrain, this includes Bricks. Also, no sub-explosion is ever left out, so say you create an explosion with 4 sub explosions in a corner of a brick house, all 4 sub explosions will appear in that corner. I am not certain when the raycast check for this is done, but I assume it's as soon as the parent explosion is created (from observations with builds blown up) It's way simpler then all this, sub-explosions seem to appear above the explosion, in a cone-shaped radius of about 60 degrees Theta-wise. There is nothing special here.
Offset is NOT scaled down!! Through events or otherwise, so prepare in advance.
Having effects die out instead of dragging on with a long-lived parent/sub explosion
This is a rather important bit, as you might have realised that with rule 1 and 2 the parent explosion and the next ones in line (assuming you're using sub-sub-explosions) might have lifetimes that make the effects last a bit too long for anyone's tastes. Here's what you can do,
Emitters
Use lifetimeMS = ##; from the emitterdata in any emitter datablock you want to kill prematurely in an explosion. It rules over an explosion's lifetimeMS, so you can cease the emitter after a specified lifetime, unless of course the explosion dies first.
**Remember, particleEmitter = SomeEmitter; is the Bulk emitter, it creates a set number of particles with both particleData and emitterData characteristics and immediately dies. You only need to worry about emitters[0 ] through [3 ] as far as emitter duration goes.
Dynamic Light
A long-lasting light effect sucks most of the time, let's face it. You can remedy this by taking the Parent explosion's light away, making it much less vibrant, making it's lifetimeMS as short as possible while encompassing the sub-explosions, or giving the sub explosions some light instead. Or a combination of these, it all works.
camShake
This thing is annoying, don't use it. Or atleast make it brief. Anyhow sub-explosions can also use the camShake functions.
And that's all folks, I hope this helps some of you. Have fun experimenting.
Edit: 2 pass-bys isn't enough it seems, this thing is littered with grammatical errors. Sorry about that.