I went back to the default (stock) starting position for the bailing crew, that being at the location of the bailout hook. At low altitudes, where the margins don't permit to wait a long time before opening the chute, there are some instances of crew pairs still having their chutes to touch and hence collapse. But the number of instances is very much reduced, to a degree satisfying enough to not feel I must introduce positional displacements from the start, thereby retaining the best behaviour for proper paratrooper drops (and cargo drops I should imagine.)
While I'm at it, here's the relevant part of AircraftState.bailout() which sets the starting position of the bailing crew and the velocity (taken from the plane's speed.) I keep the stock positioning, but leave here the experiment I tried in which a random positional offset was applied to each of the X, Y and Z axes relative to the ExternalBail hook. The 4 new lines take the plane's velocity vector, multiply it by a random value of between 0.85 to 0.95, and apply that reduced speed to the paratrooper.
try
{
Hook hook = actor.findHook("_ExternalBail0" + (i - 10));
if (hook != null)
{
Loc loc = new Loc(0.0, 0.0, 0.0, World.Rnd().nextFloat(-45.0F, 45.0F), 0.0F, 0.0F); //original
// Loc loc = new Loc(World.Rnd().nextDouble(-2.0, 2.0), World.Rnd().nextDouble(-2.0, 2.0),World.Rnd().nextDouble(-2.0, 0.0), World.Rnd().nextFloat(-45.0F, 45.0F), 0.0F, 0.0F); //experiment
hook.computePos(actor, actor.pos.getAbs(), loc);
Vector3d v = new Vector3d(); //these 4 lines are new code to apply an initial retardation to simulate the strong slipstream
v.set(aircraft.FM.Vwld);
double SpeedScale = TrueRandom.nextDouble(0.85D, 0.95D);
v.scale(SpeedScale);
// Paratrooper paratrooper = new Paratrooper(actor, actor.getArmy(), i - 11, loc, aircraft.FM.Vwld); //original
Paratrooper paratrooper = new Paratrooper(actor, actor.getArmy(), i - 11, loc, v); //to get paratroopers to start out slower than plane, falling behind in the slipstream
aircraft.FM.setTakenMortalDamage(true, null);
if (i == 11)
{
aircraft.FM.CT.WeaponControl[0] = false;
aircraft.FM.CT.WeaponControl[1] = false;
}
if (i > 10 && i <= 19)
EventLog.onBailedOut(aircraft, i - 11);
}
} catch (Exception exception)
{
/* empty */
} finally
{
/* empty */
}
if (astateBailoutStep == 19 && actor == World.getPlayerAircraft() && !World.isPlayerGunner() && aircraft.FM.brakeShoe)
MsgDestroy.Post(Time.current() + 1000L, aircraft);