Since pointing out the basic scheme in the previous post, let's illustrate the changes in the handling of effects for "House" type objects, which are most of the objects contained in static.ini, I paste here some Java from Explosions.class (I've also made some notable alterations to House.class, but I'll leave that out of this).
First, Here's the stock code in Explosions.HouseExplode(). Note that Body types Wood, Rock and Fuel are handled coarsely.
public static void HouseExplode(int i, Loc loc, float af[])
{
if(!Config.isUSE_RENDER())
return;
String s = "";
byte byte0 = 0;
float f = 1.0F;
switch(i)
{
case 0: // '\0'
f = 0.75F;
// fall through
case 1: // '\001'
s = "Wood";
byte0 = 4;
break;
case 2: // '\002'
f = 0.75F;
// fall through
case 3: // '\003'
case 4: // '\004'
s = "Rock";
byte0 = 3;
break;
case 5: // '\005'
f = 0.75F;
// fall through
case 6: // '\006'
s = "Fuel";
byte0 = 5;
break;
default:
System.out.println("WARNING: HouseExplode(): unknown type");
return;
}
String s1 = "effects/Explodes/Objects/House/" + s + "/Boiling.eff";
String s2 = "effects/Explodes/Objects/House/" + s + "/Boiling2.eff";
String s3 = "effects/Explodes/Objects/House/" + s + "/Pieces.eff";
Eff3D.initSetBoundBox(af[0], af[1], af[2], af[3], af[4], af[5]);
Eff3DActor.New(loc, 1.0F, s1, 3F);
Eff3D.initSetBoundBox(af[0] + (af[3] - af[0]) * 0.25F, af[1] + (af[4] - af[1]) * 0.25F, af[2], af[3] - (af[3] - af[0]) * 0.25F, af[4] - (af[4] - af[1]) * 0.25F, af[2] + (af[5] - af[2]) * 0.5F);
Eff3DActor.New(loc, 1.0F, s3, 3F);
if(i != 0)
{
String s4 = "effects/Explodes/Objects/House/" + s + "/Fire_Smoke.eff";
RangeRandom rangerandom = World.rndPos(loc.getX(), loc.getY());
float f1 = rangerandom.nextFloat();
if((double)f1 > 0.5D)
{
float f2 = rangerandom.nextFloat(300F, 600F);
Eff3DActor.New(loc, f, s4, f2);
Eff3DActor.New(loc, f, s2, f2);
} else
{
Eff3DActor.New(loc, f, s4, 5F);
Eff3DActor.New(loc, f, s2, 5F);
}
} else
{
Eff3DActor.New(loc, f, s2, 3F);
}
SfxExplosion.building(loc.getPoint(), byte0, af);
}
Here's my expanded Explosions.HouseExplode(). I handle all Body types in a more granular way, and add consideration of the new types Flesh and Vehicle.
public static void HouseExplode(int i, Loc loc, float fs[])
//called in House.class; i = prop.EXPL_TYPE (was 0 to 6, then 0 to 7, now 0 to 8)
{
if(!Config.isUSE_RENDER())
return;
Point3d point3d = new Point3d();
Point3d point3d1 = loc.getPoint(); //New by WxTech
o.set(0.0F, 90.0F, 0.0F); //New by WxTech
l.set(point3d1, o); //New by WxTech
String string = "";
boolean bFuel = false; //becomes true if "FuelSmall" or "Fuel", i.e., the fuel type
boolean bBig = false; //becomes true if "WoodMiddle", "RockHuge" or "FuelBig", i.e., the largest sizes of all types; did include "RockBig", but feel it might be best left out...
scaleFire = MiscEffects.cvt(World.Sun().ToSun.z, -0.25F, 0.0F, 2.0F, 1.0F); //for other than Fuel
scaleFireFuel = MiscEffects.cvt(World.Sun().ToSun.z, -0.25F, 0.0F, 1.7F, 1.0F); //for FuelBig and FuelSmall; Not as aggressive
float scaleLight = MiscEffects.cvt(World.Sun().ToSun.z, -0.25F, 0.0F, 1.0F, 0.5F);
fSmokeFireTimeFactor_1 = Config.cur.ini.get("Mods", "SmokeFireTimeFactor_Building", 4F); //Apr 3, 2024; allow player to set a factor for duration of long-lasting smoke/fire
if(fSmokeFireTimeFactor_1 < 1F)
fSmokeFireTimeFactor_1 = 1F;
if(fSmokeFireTimeFactor_1 > 100F)
fSmokeFireTimeFactor_1 = 100F;
//HUD.training("SFLTF_1: " + fSmokeFireLiveTimeFactor_1);
byte byte0; //related to explosion sound (SfxExplosion.building); 3=Rock, 4=Wood, 5=Metall
int i_alt_; //Body type value, original and alternate assignment
switch (i)
// Allowed body types are: WoodSmall, WoodMiddle, RockMiddle, RockBig, RockHuge, FuelSmall, FuelBig, Flesh, Vehicle
{
case 0: //WOOD_SMALL (and FLESH, originally)
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "Flesh"; //is smaller
i_alt_ = 7;
}
else
{
string = "WoodSmall";
i_alt_ = 0;
}
byte0 = 4;
break;
case 1: //WOOD_MIDDLE
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "WoodSmall"; //is smaller
i_alt_ = 0;
}
else
{
string = "Wood";
i_alt_ = 1;
bBig = true;
}
byte0 = 4;
break;
case 2: //ROCK_MIDDLE
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "WoodSmall"; //is similar size
i_alt_ = 0;
}
else
{
string = "RockMiddle";
i_alt_ = 2;
}
byte0 = 3;
break;
case 3: //ROCK_BIG
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "Wood"; //is about similar size
i_alt_ = 1;
}
else
{
string = "RockBig";
i_alt_ = 3;
// bBig = true; //may not want to keep this
}
byte0 = 3;
break;
case 4: //ROCK_HUGE
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "Wood"; //is smaller
i_alt_ = 1;
}
else
{
string = "Rock";
i_alt_ = 4;
bBig = true;
}
byte0 = 3;
break;
case 5: //FUEL_SMALL
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "Vehicle"; //is smaller
i_alt_ = 8;
}
else
{
string = "FuelSmall";
i_alt_ = 5;
bFuel = true;
}
byte0 = 5;
break;
case 6: //FUEL_BIG
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "FuelSmall";
i_alt_ = 5;
bFuel = true; //is fuel
}
else
{
string = "Fuel";
i_alt_ = 6;
bFuel = true; //is fuel
bBig = true;
}
byte0 = 5;
break;
case 7: //FLESH -- NEW!!!
if (TrueRandom.nextFloat() < 0.66F) //2/3 will not generate effects
return;
string = "Flesh";
i_alt_ = 7;
byte0 = 4;
break;
case 8: //VEHICLE -- NEW!!!
if (TrueRandom.nextFloat() < 0.33F) //1/3 will not generate effects
return;
if (TrueRandom.nextFloat() < 0.33F)
{
string = "Flesh";
i_alt_ = 7;
}
else
{
string = "Vehicle";
i_alt_ = 8;
}
byte0 = 5;
break;
default:
System.out.println("WARNING: HouseExplode(): unknown type");
return;
}
Eff3D.initSetBoundBox(fs[0], fs[1], fs[2], fs[3], fs[4], fs[5]); //X, Y, Z, X', Y', Z'
Eff3D.initSetBoundBox(fs[0] + (fs[3] - fs[0]) * 0.25F, fs[1] + (fs[4] - fs[1]) * 0.25F, fs[2], fs[3] - (fs[3] - fs[0]) * 0.25F, fs[4] - (fs[4] - fs[1]) * 0.25F, fs[2] + (fs[5] - fs[2]) * 0.5F); //STOCK! makes half size; -X, -Y, -Z as is, X, Y, Z midpoint
float Volume = Math.abs(fs[0] - fs[3]) * Math.abs(fs[1] - fs[4]) * Math.abs(fs[5] - fs[2]); //volume of mesh, in m^3
Eff3DActor.New(l, 1.0F, "Effects/Explodes/_Empty.eff", -1F); //NEW! this first effect gets re-scaled by the annoying BoundBox behaviour, hence making this a 'throw-away' effect
// if (Math.abs(fs[0] - fs[3]) > 20 || Math.abs(fs[1] - fs[4]) > 20 || Math.abs(fs[5] - fs[2]) > 20) //for buildings > 20m across or tall
// if (Volume > 4000F && i > 0 && i < 5) //4000m^3 is, e.g., 20 * 20 * 10, or 15.9m cubed; also only if WoodMiddle or any of the three Rock Body types
if (Volume > 4000F && i < 5 && TrueRandom.nextFloat() < 0.5F) //4000m^3 is, e.g., 20 * 20 * 10, or 15.9m cubed; for all Wood and Rock types (not for Fuel, Flesh or Vehicle)
{
// float tim = TrueRandom.nextFloat(660F, 900F); //11-15min
float tim = TrueRandom.nextFloat(50.0F, 80.0F);
float f_0_ = tim * fSmokeFireTimeFactor_1;
Eff3DActor.New(l, 1.0F, "Effects/Explodes/Objects/Building20m/Structure.eff", -1F); //chunks, always thrown
if(tim > 65F) //midway between 50 and 80; was 780=13min; midway between 660 and 900
Eff3DActor.New(l, 1.0F, "Effects/Explodes/Objects/Building20m/Smoke.eff", f_0_); //persistent lighter smoke when f_0_ longer, 13-15min
else
Eff3DActor.New(l, 1.0F, "Effects/Explodes/Objects/Building20m/Smoke2.eff", f_0_); //persistent darker smoke when f_0_ shorter, 11-13min
Eff3DActor eff3dactor = Eff3DActor.New(l, scaleFireFuel, "Effects/Explodes/Objects/Building20m/Fire.eff", TrueRandom.nextFloat(0.85F, 0.95F) * f_0_); //persistent fire, 15m
if (World.Sun().ToSun.z < 0.0F) //100% chance of light source
{
LightPointActor lightpointactor = new LightPointActor(new LightPointWorld(), new Point3d(0.0D, 0.0D, 10.0D));
lightpointactor.light.setColor(1.0F, 0.6F, 0.2F);
lightpointactor.light.setEmit(1.0F * scaleLight, 250F * scaleLight); //was 1, 200
eff3dactor.draw.lightMap().put("light", lightpointactor);
}
}else //other than big building WITH big effects above
{
String string_1_ = "Effects/Explodes/Objects/House/" + string + "/Pieces.eff"; //exploded bits (fireballs for Fuel) [was Boiling]
String string_2_ = "Effects/Explodes/Objects/House/" + string + "/BlastCloud.eff"; //ground-level blast smoke/dust [was Pieces]
String string_3_ = "Effects/Explodes/Objects/House/" + string + "/Fire.eff"; //long-lasting fire [was Boiling2]
String string_4_ = "Effects/Explodes/Objects/House/" + string + "/Smoke.eff"; //main long-lasting smoke [was Fire_Smoke]
String string_4A_ = "Effects/Explodes/Objects/House/" + string + "/Smoke_alternate.eff"; //ALTERNATE Fire_Smoke, 50% chance; denser/darker; NONE for fuel [was Fire_Smoke2]
String string_5_ = "Effects/Explodes/Objects/House/" + string + "/Smoke_billowing.eff"; //NEW!!! billowing smoke texel for FUEL_BIG only [name unchanged]
Eff3DActor.New(l, 1.0F, string_2_, -1F); //ground-level blast smoke/dust; keep unity scale for all
if (i_alt_ > 0 && i_alt_ < 7) //if i_alt_ 1 to 6, i.e., NOT WoodSmall, Flesh, Vehicle -- NEW!!!!!!!
{
if (bBig) //if of the larger sizes, create larger fire/smoke
{
// float f_1_ = TrueRandom.nextFloat(450.0F, 600.0F); //originally 300 to 600 sec duration (5 to 10 min)
float f_1_ = TrueRandom.nextFloat(40.0F, 60.0F) * fSmokeFireTimeFactor_1; //live time
if (TrueRandom.nextFloat() < 0.5F && i < 5) //May 23, 2024; to randomly select alternate smoke (denser/darker) for Wood and Rock--not fuel
Eff3DActor.New(l, 1.0F, string_4A_, f_1_); //alternate smoke
else
Eff3DActor.New(l, 1.0F, string_4_, f_1_); //smoke, 450-600 sec
if (bFuel) //if "Fuel" (big, in this case)
{
if(TrueRandom.nextFloat() < 0.2F)
Fuel_Fireball_Big(point3d1); //very prominent fireball merging into smoke
else
Eff3DActor.New(l, 1.0F, string_1_, -1F); //fireballs
Eff3DActor.New(l, 1.0F, string_5_, f_1_ * 0.9F); //Smoke_billowing, lasts as long as does the full-duration fire
Eff3DActor eff3dactor = Eff3DActor.New(l, scaleFireFuel, string_3_, f_1_ * 0.9F); //fire; 450-600 sec * 0.9
if (World.Sun().ToSun.z < 0.0F) //100% chance of light source
{
LightPointActor lightpointactor = new LightPointActor(new LightPointWorld(), new Point3d());
lightpointactor.light.setColor(1.0F, 0.6F, 0.2F);
lightpointactor.light.setEmit(1.0F * scaleLight, 200F * scaleLight); //was 1, 150
eff3dactor.draw.lightMap().put("light", lightpointactor);
}
}else //if not "Fuel"
{
if (TrueRandom.nextFloat() < 0.7F)
{
Eff3DActor.New(l, 1.0F, string_1_, -1F); //exploded bits
Eff3DActor eff3dactor = Eff3DActor.New(l, scaleFire, string_3_, f_1_ * 0.85F); //fire
if (World.Sun().ToSun.z < 0.0F && TrueRandom.nextFloat() < 0.1F) //NEW! Had at 20%; 10% chance of light source for larger objects
{
LightPointActor lightpointactor = new LightPointActor(new LightPointWorld(), new Point3d());
lightpointactor.light.setColor(1.0F, 0.6F, 0.2F);
lightpointactor.light.setEmit(1.0F * scaleLight, 175F * scaleLight);
eff3dactor.draw.lightMap().put("light", lightpointactor);
}
}
}
} else //if of the small size (NOT bBig)
{
// float f_2_ = TrueRandom.nextFloat(280.0F, 450.0F); //originally 100 to 200 sec duration
float f_2_ = TrueRandom.nextFloat(25.0F, 45.0F) * fSmokeFireTimeFactor_1;
if (TrueRandom.nextFloat() < 0.5F && i < 5) //May 23, 2024; to randomly select alternate smoke (denser/darker) for Wood and Rock--not fuel
Eff3DActor.New(l, 1.0F, string_4A_, f_2_); //alternate smoke
else
Eff3DActor.New(l, 1.0F, string_4_, f_2_); //smoke, was 5 sec
if (bFuel) //if "Fuel" (small, in this case)
{
if(TrueRandom.nextFloat() < 0.2F)
Fuel_Fireball(point3d1); //prominent fireball merging into smoke
else
Eff3DActor.New(l, 1.0F, string_1_, -1F); //fireballs
Eff3DActor.New(l, 0.9F, "Effects/Smokes/SmokeOilTank4.eff", f_2_ * 0.9F); //NEW effect; animated billowing smoke (for train oil wagons); 280-450 sec * 0.9; NOTE SCALE FACTOR
Eff3DActor eff3dactor = Eff3DActor.New(l, scaleFireFuel, string_3_, f_2_ * 0.9F); //fire; 280-450 sec * 0.9
if (World.Sun().ToSun.z < 0.0F && TrueRandom.nextFloat() < 0.3F) //30% chance of light source
{
LightPointActor lightpointactor = new LightPointActor(new LightPointWorld(), new Point3d());
lightpointactor.light.setColor(1.0F, 0.6F, 0.2F);
lightpointactor.light.setEmit(1.0F * scaleLight, 100F * scaleLight);
eff3dactor.draw.lightMap().put("light", lightpointactor);
}
}else //if not "Fuel"
{
if (TrueRandom.nextFloat() < 0.7F)
Eff3DActor.New(l, scaleFire, string_3_, f_2_ * 0.85F); //fire; 70% chance
Eff3DActor.New(l, 1.0F, string_1_, -1F); //exploded bits; always
}
}
} else //if i_alt_ = 0, 7, or 8 (WoodSmall, Flesh, Vehicle)
if (i_alt_ == 0 || i_alt_ == 7 || i_alt_ == 8)
{
// float f_3_ = TrueRandom.nextFloat(180.0F, 360.0F); //3 - 6 min; originally 30 to 60 sec duration
float f_3_ = TrueRandom.nextFloat(20.0F, 40.0F) * fSmokeFireTimeFactor_1; //live time
if (i_alt_ == 7) //if Flesh (NO FIRE)
{
f_3_ *= 0.33F; //make live time last 1/3 as long, or 1.5 - 3 min
if (TrueRandom.nextFloat() < 0.33F) //make smoke effect occur in 1/3 of instances (in addition to the already 1/3 probability)
{
if (TrueRandom.nextFloat() < 0.5F) //May 23, 2024; to randomly select alternate smoke (denser/darker)
Eff3DActor.New(l, 1.0F, string_4A_, f_3_); //alternate smoke
else
Eff3DActor.New(l, 1.0F, string_4_, f_3_); //smoke ONLY, no fire
}
} else //if i_alt_ = 0 or 8 (WoodSmall, Vehicle)
{
if (TrueRandom.nextFloat() < 0.7F)
{
if (TrueRandom.nextFloat() < 0.5F) //May 23, 2024; to randomly select alternate smoke (denser/darker)
Eff3DActor.New(l, 1.0F, string_4A_, f_3_); //alternate smoke
else
Eff3DActor.New(l, 1.0F, string_4_, f_3_); //smoke
if (TrueRandom.nextFloat() < 0.7F)
Eff3DActor.New(l, scaleFire, string_3_, f_3_ * 0.85F); //fire; 50% net chance; 180-360 sec * 0.85
}
Eff3DActor.New(l, 1.0F, string_1_, -1F); //Boiling; exploded bits, always
}
}
}
SfxExplosion.building(loc.getPoint(), byte0, fs);
}
I've added a NEW secondary explosion effect, implemented randomly for suitable objects by the new method Explosions.HouseSecondaryExplode():
public static void HouseSecondaryExplode(float f, Loc loc)
//NEW! called from House.runDeathShow(); f = prop.SECONDARY_EXPL (1=big blast, 2=big fireball, 3=hybrid big blast/fireball, 4=small fireball)
{
if (f < 0.5F) //valid values are 1, 2, 3 or 4
return;
if(!Config.isUSE_RENDER())
return;
Point3d point3d = new Point3d();
Point3d point3d1 = loc.getPoint();
o.set(0.0F, 90.0F, 0.0F);
l.set(point3d1, o);
if (((f > 0.5F && f < 1.5F) || (f > 2.5F && f < 3.5F)) && TrueRandom.nextFloat() < 0.25F) //if f = 1 for blast or 3 for hybrid; had prob 0.15
{
final Loc loc_1 = new Loc(point3d1);
double tim = TrueRandom.nextDouble(10.0, 20.0); //was 10, 20
new MsgAction(tim)
{
public void doAction(Object obj)
{
Point3d point3d2 = new Point3d();
point3d2 = loc_1.getPoint();
SecondaryExpl(point3d2); //sound is part of method
}
};
if (f > 2.5F && f < 3.5F && TrueRandom.nextFloat() < 0.5F) //add chance of fireball if "3"; make prob about 0.5
{
new MsgAction(tim + TrueRandom.nextDouble(5.0, 8.0)) //delays fireball by 5-8s after start of blast
{
public void doAction(Object obj)
{
Point3d point3d2 = new Point3d();
point3d2 = loc_1.getPoint();
Fuel_Fireball_Big(point3d2); //sound is part of method
}
};
}
}
if (f > 1.5F && f < 2.5F && TrueRandom.nextFloat() < 0.2F) //if f = 2, for fireball alone; had prob 0.15
{
final Loc loc_1 = new Loc(point3d1);
new MsgAction(TrueRandom.nextDouble(10.0, 20.0)) //was 10, 20
{
public void doAction(Object obj)
{
Point3d point3d2 = new Point3d();
point3d2 = loc_1.getPoint();
Fuel_Fireball_Big(point3d2); //sound is part of method
}
};
}
if (f > 3.5F && f < 4.5F && TrueRandom.nextFloat() < 0.15F) //if f = 4, for small fireball alone (good for, e.g., fuel barrels)
{
final Loc loc_1 = new Loc(point3d1);
new MsgAction(TrueRandom.nextDouble(7.0, 14.0)) //was 7, 14
{
public void doAction(Object obj)
{
Point3d point3d2 = new Point3d();
point3d2 = loc_1.getPoint();
Fuel_Fireball(point3d2); //sound is part of method
}
};
}
}
And to generate the secondary explosions themselves, with ballistic particles of firey smoke trails, this NEW method, Explosions.SecondaryExpl() was written:
public static void SecondaryExpl(Point3d point3d)
//NEW! for static objects, like buildings, etc.; patterned after ExplodeAmmo; do not tie to explosive damage--too potentially dangerous for wild chain reactions.
{
if(!Config.isUSE_RENDER())
return;
Loc loc = new Loc(point3d);
o.set(0.0F, 90.0F, 0.0F);
loc.set(point3d, o);
float f1 = TrueRandom.nextFloat(1.0F, 1.5F); //range of flash/ammovag fireball size, native 40m expanding to 100m diam. (now up to 60-150)
Eff3DActor.New(loc, f1, "Effects/Explodes/Objects/ExplodeAmmo/Smoke.eff", -1F);
Eff3DActor.New(loc, f1, "Effects/Explodes/Objects/ExplodeAmmo/Ammovag_expl.eff", -1F); //slower fireball
Eff3DActor.New(loc, 1.0F, "Effects/Explodes/Objects/ExplodeAmmo/Shock.eff", -1F);
Eff3DActor.New(loc, 1.0F, "Effects/Explodes/Objects/ExplodeAmmo/Sparks.eff", -1F);
Eff3DActor.New(loc, 1.0F, "Effects/Explodes/Objects/ExplodeAmmo/Pieces.eff", -1F);
Eff3DActor eff3dactor = Eff3DActor.New(loc, f1, "Effects/Explodes/Objects/ExplodeAmmo/Burn.eff", -1F); //rapid flash, live time 0.6s
if (World.Sun().ToSun.z < 0.0F)
{
float scaleLight = MiscEffects.cvt(World.Sun().ToSun.z, -0.25F, 0.0F, 1.0F, 0.5F);
LightPointActor lightpointactor = new LightPointActor(new LightPointWorld(), new Point3d());
lightpointactor.light.setColor(1.0F, 0.6F, 0.2F);
lightpointactor.light.setEmit(1.0F * scaleLight, 250F * f1 * scaleLight);
eff3dactor.draw.lightMap().put("light", lightpointactor);
}
Vector3d vector3d = new Vector3d();
int j = TrueRandom.nextInt(4, 8); //4 to 7 each FAST and SLOW ballistic particles
for (int j_1_ = 0; j_1_ < j; j_1_++)
{
vector3d.set((double) TrueRandom.nextFloat(-1.0F, 1.0F), (double) TrueRandom.nextFloat(-1.0F, 1.0F), (double) TrueRandom.nextFloat(0.5F, 1.0F)); //had Z as (0.6, 1)
vector3d.normalize();
vector3d.scale((double) TrueRandom.nextFloat(120.0F, 240.0F)); //speed scale factor, to get m/s; had 180, 240
float f = TrueRandom.nextFloat(0.5F, 0.625F); //range of live time in seconds; was 0.4, 0.5
BallisticProjectile ballisticprojectile = new BallisticProjectile(loc.getPoint(), vector3d, f);
Eff3DActor.New(ballisticprojectile, null, null, 1.0F, "Effects/Explodes/Objects/ExplodeAmmo/SmokeTendril.eff", f);
vector3d.set((double) TrueRandom.nextFloat(-1.0F, 1.0F), (double) TrueRandom.nextFloat(-1.0F, 1.0F), (double) TrueRandom.nextFloat(0.5F, 1.0F));
vector3d.normalize();
vector3d.scale((double) TrueRandom.nextFloat(20.0F, 60.0F)); //speed scale factor, to get m/s; was 30, 50
float f_1_ = TrueRandom.nextFloat(9F, 14F); //range of live time in seconds; was 9, 13
ballisticprojectile = new BallisticProjectile(loc.getPoint(), vector3d, f_1_);
if (TrueRandom.nextFloat() < 0.5F)
{
Eff3DActor.New(ballisticprojectile, null, null, 1.0F, "3DO/Effects/Aircraft/EngineSmokeMediumSPD.eff", f_1_);
Eff3DActor.New(ballisticprojectile, null, null, 1.0F, "3DO/Effects/Aircraft/EngineSmokeMediumTSPD.eff", f_1_);
Eff3DActor.New(ballisticprojectile, null, null, 1.0F, "Effects/Explodes/Wreckage_Burn_2.eff", f_1_);
} else
{
Eff3DActor.New(ballisticprojectile, null, null, 1.0F, "Effects/Explodes/Wreckage_Burn_2.eff", f_1_ * 1.5F); //NEW effect
Eff3DActor.New(ballisticprojectile, null, null, 1.0F, "Effects/Explodes/Wreckage_Smoke_2.eff", f_1_ * 1.5F); //NEW effect, thinner smoke trail
}
}
// SfxExplosion.crashAir(point3d, 0); //0=sound on land, 1=sound in air, 2=sound on water
SfxExplosion.shell(point3d, 0, 300, 0, 300); //(air/water/land, power (50 is transition betwen "middle" and "big"), powerType (0 = no splinters), range)
o.set(0.0F, 0.0F, 0.0F);
l.set(point3d, o);
ExplodeSurfaceWave(0, 208F, 0.4F); //texture expansion 520m/s
if (point3d.z - Engine.land().HQ_Air(point3d.x, point3d.y) < 36.0) //from Bomb250 Object
{
if (Engine.land().isWater(point3d.x, point3d.y)) //add 24 to 35 small water shrapnel hits randomly placed around explosion
shrapnelSplashWater(point3d, 27, 41, 40F, 0.8F, 0.25F, 5F, 3F); //was 7, 3
else
if (!Engine.land().isWater(point3d.x, point3d.y)) //superfluous?
shrapnelSplashLand(point3d, 27, 41, 40F, 0.8F);
}
}