For those who are curious to see how the sausage is made.
Here's the method which creates the flak bursts, updated with my variation on Storebror's flak illumination mod (including my addition of conf.ini entries to select whether or not to generate the illumination for each of the two size classes of flak). Toward the bottom is the new code to send the relevant parameters to the new methods that make the water and ground shrapnel hits.
public static void AirFlak(Point3d point3d, int i)
{
if (Config.isUSE_RENDER())
{
o.set(0.0F, 90.0F, 0.0F);
l.set(point3d, o);
String string = "Effects/Explodes/Air/Zenitka/";
boolean bBurnFade = false;
switch (i)
{
case 0:
string += "USSR_85mm/";
bBurnFade = true;
lightPointIntensity = 1.0F;
lightPointRange = 150F;
break;
case 1:
string += "Germ_88mm/";
bBurnFade = true;
lightPointIntensity = 1.0F;
lightPointRange = 150F;
break;
case 2:
string += "USSR_25mm/";
lightPointIntensity = 0.7F;
lightPointRange = 20.0F;
break;
default:
string += "Germ_20mm/";
lightPointIntensity = 0.7F;
lightPointRange = 20.0F;
}
SfxExplosion.zenitka(point3d, i);
Eff3DActor.New(l, 1.0F, string + "Sparks.eff", -1.0F);
Eff3DActor.New(l, 1.0F, string + "SmokeBoiling.eff", -1.0F);
if (bBurnFade)
Eff3DActor.New(l, 1.0F, string + "Fire.eff", -1.0F);
if (World.Sun().ToSun.z > 0.0F)
Eff3DActor.New(l, 1.0F, string + "Burn.eff", -1.0F);
else
{
float burnSize = MiscEffects.cvt(World.Sun().ToSun.z, -0.25F, 0.0F, 1.4F, 1.0F);
Eff3DActor.New(l, burnSize, string + "Burn_night.eff", -1.0F);
if ((Config.cur.ini.get("Mods", "LightFlakIllumination", 0) == 1 && i > 1) || (Config.cur.ini.get("Mods", "HeavyFlakIllumination", 0) == 1 && i < 2))
{
lightPointIntensity *= MiscEffects.cvt(World.Sun().ToSun.z, -0.25F, 0.0F, 1.0F, 0.25F); //was scaled 1.0, 0.5; tried 2, 0.3
lightPointRange *= MiscEffects.cvt(World.Sun().ToSun.z, -0.25F, 0.0F, 1.0F, 0.3F); //was scaled 1.0, 0.5; tried 1.5, 0.3
Eff3DActor eff3dactor = Eff3DActor.New(l, 1.0F, "Effects/Explodes/Cannon/Object/light.eff", 0.06F);
eff3dactor.postDestroy(Time.current() + 60L); //night flash effect lasts 0.06s
LightPointActor lightpointactor = new LightPointActor(new LightPointWorld(), new Point3d());
lightpointactor.light.setColor(1.0F, 0.6F, 0.2F);
lightpointactor.light.setEmit(lightPointIntensity, lightPointRange);
eff3dactor.draw.lightMap().put("light", lightpointactor);
}
}
if (i > 1 && point3d.z - Engine.land().HQ_Air(point3d.x, point3d.y) < 10) //small flak shrapnel splash/dust
{
if (Engine.land().isWater(point3d.x, point3d.y))
shrapnelSplashWater(point3d, 5, 9, 5F, 0.5F, 0F, 1F, 1F);
else
shrapnelSplashLand(point3d, 5, 9, 5F, 0.5F, 0F);
}
if (i < 2 && point3d.z - Engine.land().HQ_Air(point3d.x, point3d.y) < 20) //large flak shrapnel splash/dust
{
if (Engine.land().isWater(point3d.x, point3d.y))
shrapnelSplashWater(point3d, 7, 12, 9F, 0.6F, 0F, 1F, 1F);
else
shrapnelSplashLand(point3d, 7, 12, 9F, 0.6F, 0F);
}
}
}
Here are the two new methods to create shrapnel splash/hits. They are used by other methods, such as bomb, rocket and larger shell bursts against objects.
public static void shrapnelSplashWater(Point3d point3d, int iLo, int iHi, float fRad, float fScale, float fProb, float fSize, float fTime)
// iLo = low # splashes, iHi = high # splashes, fRad = Gaussian radius, fScale = scaler for splash size, fProb = probability for larger splash/ring, fSize = ring finish size, fTime = ring live time
{
if (Config.isUSE_RENDER())
{
float shrapnelScale;
int i_1 = TrueRandom.nextInt(iLo, iHi);
for (int i_0 = 0; i_0 < i_1; i_0++)
{
Point3d point3d_1 = new Point3d(point3d);
float d = (float)World.Rnd().nextGaussian() * fRad;
point3d_1.x += d;
d = (float)World.Rnd().nextGaussian() * fRad;
point3d_1.y += d;
World.cur();
point3d_1.z = World.land().HQ(point3d_1.x, point3d_1.y);
shrapnelScale = fScale * TrueRandom.nextFloat(0.7F, 1.3F);
if (TrueRandom.nextFloat() < fProb)
{
shrapnelScale = fScale * 1.4F;
o.set(0.0F, 0.0F, 0.0F);
l.set(point3d_1, o);
new ActorSnapToLand("3do/Effects/Explosion/WaterRing.sim", true, l, 0.2F, 1F, fSize, 1.0F, 0.0F, fTime);
}
o.set(0.0F, 90.0F, 0.0F);
l.set(point3d_1, o);
Eff3DActor.New(l, shrapnelScale, "Effects/Explodes/Debris/FragSplash/FontainWater.eff", -1F);
Eff3DActor.New(l, shrapnelScale, "Effects/Explodes/Debris/FragSplash/FontainWater2.eff", -1F);
}
}
}
public static void shrapnelSplashLand(Point3d point3d, int iLo, int iHi, float fRad, float fScale, float fProb)
// iLo = low # dustcloud, iHi = high # dustcloud, fRad = Gaussian radius, fScale = scaler for dustcloud, fProb = probability for larger dustcloud
{
if (Config.isUSE_RENDER())
{
float shrapnelScale;
int i_1 = TrueRandom.nextInt(iLo, iHi);
for (int i_0 = 0; i_0 < i_1; i_0++)
{
Point3d point3d_1 = new Point3d(point3d);
float d = (float)World.Rnd().nextGaussian() * fRad;
point3d_1.x += d;
d = (float)World.Rnd().nextGaussian() * fRad;
point3d_1.y += d;
World.cur();
point3d_1.z = World.land().HQ(point3d_1.x, point3d_1.y);
shrapnelScale = fScale * TrueRandom.nextFloat(0.7F, 1.3F);
if (TrueRandom.nextFloat() < fProb)
shrapnelScale = fScale * 1.4F;
o.set(0.0F, 90.0F, 0.0F);
l.set(point3d_1, o);
Eff3DActor.New(l, shrapnelScale, "Effects/Explodes/Debris/FragSplash/FontainLand.eff", -1F);
Eff3DActor.New(l, shrapnelScale, "Effects/Explodes/Debris/FragSplash/FontainLand2.eff", -1F);
}
}
}