In our stock game aircraft crashes are always the same, for every plane, every time. Absolutely unvarying. I have already introduced code to add more variation within the relevant methods, Explosions.AirDrop_Land() and Explosions.AirDrop_Water(). Method Aircraft.doExplosion() calls these methods in Explosions.class. I have recently added more functionality here, as well, by invoking other effects in 6 other methods in Explosions.class. Two of these methods (ExplodeAmmo() and ExplodeAmmoSmall()) are my own inventions.
Furthermore, I check for the number of engines and the vertical velocity at impact, and use the latter as a scaler for the probability of invoking the effects (if a first randomized check is first true.) The effects invoked here beyond the basic "AirDrop_" and "ExplodeFuel" methods do not occur always; there is a random chance of their invocation. This adds yet more variety and unpredictability of the result of a crash.
STOCK Aircraft.doExplosion()
protected void doExplosion()
{
if(FM.Loc.z < Engine.cur.land.HQ_Air(FM.Loc.x, FM.Loc.y) + (double)(FM.Length / 2.0F))
{
World.cur();
if(World.land().isWater(FM.Loc.x, FM.Loc.y))
Explosions.AirDrop_Water(FM.Loc);
else
Explosions.AirDrop_Land(FM.Loc);
} else
{
Explosions.ExplodeFuel(FM.Loc);
}
}
My modded Aircraft.doExplosion()
protected void doExplosion()
{
Vector3d vector3d = new Vector3d(); //NEW, to get vertical velocity
vector3d.set(FM.Vwld); //m/s
if(FM.Loc.z < Engine.cur.land.HQ_Air(FM.Loc.x, FM.Loc.y) + (double)(FM.Length / 2.0F))
{
iEng = FM.EI.getNum(); //NEW; # of engines
iExplode = 0; //initialize; 1 or 2 invoke Aircraft/Land/Base_expl1.eff or Base_expl2.eff, respectively; not needed when a bomb-based effect is used, and so set to "0"
World.cur();
if(World.land().isWater(FM.Loc.x, FM.Loc.y)) //on water ===========================================================================================================
{
if((this instanceof TypeBomber) && TrueRandom.nextFloat() < 0.18F + cvt((float) vector3d.z, -10F, -50F, 0F, 0.2F)) //all bombers
{
if(TrueRandom.nextFloat() < 0.5F) //all bombers
{
Explosions.ExplodeAmmo(FM.Loc, 0);
iExplode = 2;
}
else
if(TrueRandom.nextFloat() < 0.5F)
{
if(iEng > 1) //multi-engined bomber
Explosions.BOMB1000a_Object(FM.Loc, -1.0F, 1.0F); //iExplode = 0; //to not have additional ground dust
else //single-engined bomber
if(iEng < 2)
Explosions.BOMB250_object(FM.Loc, -1.0F, 1.0F); //iExplode = 0;
}
else
{
Explosions.ExplodeAmmoSmall(FM.Loc, 0); //all bombers
iExplode = 1;
}
}
if(iEng > 1 && !(this instanceof TypeBomber) && TrueRandom.nextFloat() < 0.1F + cvt((float) vector3d.z, -10F, -50F, 0F, 0.2F)) //multi-engine, not bomber
{
if(TrueRandom.nextFloat() < 0.5F)
{
Explosions.ExplodeAmmo(FM.Loc, 2);
iExplode = 2;
}
else
{
Explosions.ExplodeAmmoSmall(FM.Loc, 2);
iExplode = 1;
}
}
if(iEng > 0 && iEng < 2 && !(this instanceof TypeBomber) && TrueRandom.nextFloat() < 0.1F + cvt((float) vector3d.z, -15F, -75F, 0F, 0.1F)) //single-engine, not bomber
{
Explosions.ExplodeAmmoSmall(FM.Loc, 2);
iExplode = 1;
}
Explosions.AirDrop_Water(FM.Loc, iEng, iExplode); //iEng and iExplode added by WxTech
}
else //on land ===========================================================================================================================
{
if((this instanceof TypeBomber) && TrueRandom.nextFloat() < 0.35F) //all bombers; had 0.35
{
if(TrueRandom.nextFloat() < 0.5F) //all bombers
{
Explosions.ExplodeAmmo(FM.Loc, 0);
iExplode = 2;
}
else
if(TrueRandom.nextFloat() < 0.5F)
{
if(iEng > 1) //multi-engined bomber
Explosions.BOMB1000a_Land(FM.Loc, 4.0F, 1.0F, false, true); //iExplode = 0; //to not have additional ground dust
else //single-engined bomber
if(iEng < 2)
Explosions.BOMB250_Land(FM.Loc, 4.0F, 1.0F, false, true); //iExplode = 0;
}
else
{
Explosions.ExplodeAmmoSmall(FM.Loc, 0); //all bombers
iExplode = 1;
}
}
if(iEng > 1 && !(this instanceof TypeBomber) && TrueRandom.nextFloat() < 0.25F) //multi-engine, not bomber
{
if(TrueRandom.nextFloat() < 0.3F)
{
Explosions.ExplodeAmmo(FM.Loc, 0);
iExplode = 2;
}
else
if(TrueRandom.nextFloat() < 0.2F + cvt((float) vector3d.z, -10F, -50F, 0F, 0.3F)) //VSI range -20 to -100kt
Explosions.BOMB250_Land(FM.Loc, 4.0F, 1.0F, false, true); //iExplode = 0;
else
{
Explosions.ExplodeAmmoSmall(FM.Loc, 0);
iExplode = 1;
}
}
if(iEng > 0 && iEng < 2 && !(this instanceof TypeBomber) && TrueRandom.nextFloat() < 0.2F) //single-engine, not bomber
{
if(TrueRandom.nextFloat() < 0.2F + cvt((float) vector3d.z, -20F, -75F, 0F, 0.3F)) //VSI range -40 to -150kt
Explosions.BOMB250_Land(FM.Loc, 4.0F, 1.0F, false, true); //iExplode = 0;
else
{
Explosions.ExplodeAmmoSmall(FM.Loc, 0);
iExplode = 1;
}
}
Explosions.AirDrop_Land(FM.Loc, iEng, iExplode);
}
} else //in air ===========================================================================================================================
Explosions.ExplodeFuel(FM.Loc, iEng); //explosion in air, above the surface by farther than 1/2 aircraft size; same effects used by AircraftState.doExplodeTank()
}