It's long bugged me that in so many instances AI will inexplicably stay with clearly disabled planes all the way to crashing. One particularly egregious offender is the Wildcat. It seems the aileron controls are quite prone to being hit--as you'll see below. The stock treatment caused the pilot to ignore his impending doom, and legion are the instances where I've watched the idiots meekly stay aboard their crate as it slowly spirals to earth with disabled ailerons.
For the three control surface systems, aileron, elevator and rudder, AircraftState.doSetControlsDamage() renders the control ineffective, which can lead to a crash. Unless some other triggering event causes a bailout, the AI sticks with the crate no matter what.
I've expanded upon the method by adding conditional checks (with some randomization) by which to cause a bailout. I include two output runs to check on what the code is doing. This output goes to log.lst (via the temporarily active System.out.println() commands). The mission is my 9 Zeros vs 12 Wildcats, where I knocked down the vast majority. The enemy are identified by their assigned number and an asterisk (no asterisk present denotes a friendly). Note that there can be multiple instances of the triggering event, depending on how much I'm pummelling the crap out of the victim. A "hit" event identifies the stock result; the "----bail" events are the result of my new code. Previously, no bailout would have been commanded.
Different planes can have vastly differing 'sensitivity' to controls damage. As noted, the Wildcat has particularly easy-to-hit aileron cables. Some planes can be blasted to bits in great numbers with few or even no triggering events!
In the end, I'm rather liking the reduction of instances of AI drones mindlessly going down to their doom with dead controls, now having them rather more likely taking to their 'chutes.
STOCK AircraftState.doSetControlsDamage()
private void doSetControlsDamage(int i, Actor actor1)
{
switch(i)
{
case 0: // '\0'
aircraft.FM.CT.resetControl(0);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasAileronControl)
HUD.log("FailedAroneAU");
aircraft.FM.CT.bHasAileronControl = false;
aircraft.FM.setCapableOfACM(false);
break;
case 1: // '\001'
aircraft.FM.CT.resetControl(1);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasElevatorControl)
HUD.log("FailedVatorAU");
aircraft.FM.CT.bHasElevatorControl = false;
aircraft.FM.setCapableOfACM(false);
if(Math.abs(aircraft.FM.Vwld.z) > 7D)
aircraft.FM.setCapableOfBMP(false, actor1);
break;
case 2: // '\002'
aircraft.FM.CT.resetControl(2);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasRudderControl)
HUD.log("FailedRudderAU");
aircraft.FM.CT.bHasRudderControl = false;
break;
default:
throw new RuntimeException("(" + aircraft.typedName() + ") A.S.: Corrupt data in (C.A.D./null)");
}
}
My modded method:
private void doSetControlsDamage(int i, Actor actor1)
{
switch(i)
{
case 0: // '\0' //AILERON
aircraft.FM.CT.resetControl(0);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasAileronControl)
HUD.log("FailedAroneAU");
aircraft.FM.CT.bHasAileronControl = false;
aircraft.FM.setCapableOfACM(false);
System.out.println("Ail_ctrl_hit " + aircraft.typedName());
Aircraft.debugprintln(aircraft, "Aileron control damaged! ");
if(TrueRandom.nextInt(0, 99) < 50 + aircraft.FM.subSkill * 3 || (!(aircraft.FM.CT.bHasRudderControl) && TrueRandom.nextInt(0, 99) < 80 + aircraft.FM.subSkill * 3)) //ace (3) more likely to bail
{
aircraft.FM.setCapableOfBMP(false, actor1); //superfluous?
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Aileron control cut, bailing out! ");
System.out.println("Ail cut----bail, Rud_ctl?" + aircraft.FM.CT.bHasRudderControl + " " + aircraft.typedName());
hitDaSilk();
}
break;
case 1: // '\001' //ELEVATOR
aircraft.FM.CT.resetControl(1);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasElevatorControl)
HUD.log("FailedVatorAU");
aircraft.FM.CT.bHasElevatorControl = false;
aircraft.FM.setCapableOfACM(false);
System.out.println("Elev_ctrl_hit " + aircraft.typedName());
if(Math.abs(aircraft.FM.Vwld.z) > 7D) //7m/s ~14kt; keeping this separate
{
aircraft.FM.setCapableOfBMP(false, actor1);
System.out.println("Elev_no_BMP " + aircraft.typedName());
}
Aircraft.debugprintln(aircraft, "Elevator control damaged! ");
if(Math.abs(aircraft.FM.Vwld.z) < -21D || TrueRandom.nextInt(0, 99) < 75 + aircraft.FM.subSkill * 3) //21m/s ~42kt
{
aircraft.FM.setCapableOfBMP(false, actor1);
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Elevator control cut, bailing out! ");
System.out.println("Elev_cut----bail, VSI(m/s):" + aircraft.FM.Vwld.z + " " +aircraft.typedName());
hitDaSilk();
}
break;
case 2: // '\002' //RUDDER
aircraft.FM.CT.resetControl(2);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasRudderControl)
HUD.log("FailedRudderAU");
aircraft.FM.CT.bHasRudderControl = false;
System.out.println("Rud_ctrl_hit " + aircraft.typedName());
Aircraft.debugprintln(aircraft, "Rudder control damaged! ");
if((!(aircraft.FM.CT.bHasElevatorControl) && TrueRandom.nextInt(0, 99) < 80 + aircraft.FM.subSkill * 3) || (!(aircraft.FM.CT.bHasAileronControl) && TrueRandom.nextInt(0, 99) < 80 + aircraft.FM.subSkill * 3) || TrueRandom.nextInt(0, 99) < 10 + aircraft.FM.subSkill * 2)
{
aircraft.FM.setCapableOfACM(false);
aircraft.FM.setCapableOfBMP(false, actor1); //superfluous?
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Rudder control cut, bailing out! ");
System.out.println("Rud_cut----bail, Ail_ctl?" + aircraft.FM.CT.bHasAileronControl + " " + aircraft.typedName());
hitDaSilk();
}
break;
default:
throw new RuntimeException("(" + aircraft.typedName() + ") A.S.: Corrupt data in (C.A.D./null)");
}
}
9 Zeros v 12 Wildcats, run #1: (bailouts for 1, 2, 4, 5, 7, 9 and 11)
-----------------------------
[2024-02-17 03:05:33.333] dT: 3405 Ail_ctrl_hit 07*
[2024-02-17 03:05:33.333] dT: 0 Ail cut----bail, Rud_ctl?true 07*
[2024-02-17 03:06:09.502] dT: 952 Ail_ctrl_hit 5
[2024-02-17 03:06:23.026] dT: 450 Ail_ctrl_hit 02*
[2024-02-17 03:06:23.026] dT: 0 Ail cut----bail, Rud_ctl?true 02*
[2024-02-17 03:06:27.476] dT: 149 Ail_ctrl_hit 11*
[2024-02-17 03:06:27.476] dT: 0 Ail cut----bail, Rud_ctl?true 11*
[2024-02-17 03:07:15.513] dT: 819 Ail_ctrl_hit 04*
[2024-02-17 03:07:23.773] dT: 275 Ail_ctrl_hit 04*
[2024-02-17 03:07:23.836] dT: 2 Ail_ctrl_hit 04*
[2024-02-17 03:07:23.900] dT: 2 Ail_ctrl_hit 04*
[2024-02-17 03:07:23.900] dT: 0 Ail cut----bail, Rud_ctl?true 04*
[2024-02-17 03:07:52.852] dT: 966 Rud_ctrl_hit 09*
[2024-02-17 03:08:08.503] dT: 521 Ail_ctrl_hit 05*
[2024-02-17 03:08:08.503] dT: 0 Ail cut----bail, Rud_ctl?true 05*
[2024-02-17 03:08:56.804] dT: 1610 Ail_ctrl_hit 01*
[2024-02-17 03:08:56.804] dT: 0 Ail cut----bail, Rud_ctl?true 01*
[2024-02-17 03:09:49.732] dT: 1645 Ail_ctrl_hit 09*
[2024-02-17 03:09:49.732] dT: 0 Ail cut----bail, Rud_ctl?false 09*
9 Zeros v 12 Wildcats, run #2: (Much more 7.7mm fire than 20mm, hence the numerous multiple events; bailouts for 1, 2, 3, 4, 7, 8 and 11)
-----------------------------
[2024-02-17 03:12:07.321] dT: 3184 Rud_ctrl_hit 11*
[2024-02-17 03:12:07.321] dT: 0 Rud_cut----bail, Ail_ctl?true 11*
[2024-02-17 03:12:39.970] dT: 1088 Ail_ctrl_hit 07*
[2024-02-17 03:12:39.971] dT: 0 Ail cut----bail, Rud_ctl?true 07*
[2024-02-17 03:13:21.399] dT: 1381 Ail_ctrl_hit 08*
[2024-02-17 03:13:21.399] dT: 0 Ail cut----bail, Rud_ctl?true 08*
[2024-02-17 03:13:22.194] dT: 27 Ail_ctrl_hit 08*
[2024-02-17 03:13:22.194] dT: 0 Ail cut----bail, Rud_ctl?true 08*
[2024-02-17 03:13:23.273] dT: 35 Ail_ctrl_hit 08*
[2024-02-17 03:13:23.544] dT: 10 Ail_ctrl_hit 08*
[2024-02-17 03:13:27.067] dT: 117 Ail_ctrl_hit 08*
[2024-02-17 03:13:27.067] dT: 0 Ail cut----bail, Rud_ctl?true 08*
[2024-02-17 03:14:27.066] dT: 2000 Ail_ctrl_hit 04*
[2024-02-17 03:14:27.066] dT: 0 Ail cut----bail, Rud_ctl?true 04*
[2024-02-17 03:14:29.481] dT: 81 Ail_ctrl_hit 04*
[2024-02-17 03:14:29.481] dT: 0 Ail cut----bail, Rud_ctl?true 04*
[2024-02-17 03:14:41.650] dT: 185 Ail_ctrl_hit 04*
[2024-02-17 03:15:03.487] dT: 728 Ail_ctrl_hit 05*
[2024-02-17 03:15:03.487] dT: 0 Ail cut----bail, Rud_ctl?true 05*
[2024-02-17 03:15:22.456] dT: 632 Ail_ctrl_hit 03*
[2024-02-17 03:15:22.456] dT: 0 Ail cut----bail, Rud_ctl?true 03*
[2024-02-17 03:16:15.351] dT: 1655 Ail_ctrl_hit 02*
[2024-02-17 03:16:15.352] dT: 0 Ail cut----bail, Rud_ctl?true 02*
[2024-02-17 03:16:18.731] dT: 113 Ail_ctrl_hit 02*
[2024-02-17 03:16:18.731] dT: 0 Ail cut----bail, Rud_ctl?true 02*
[2024-02-17 03:16:47.684] dT: 965 Ail_ctrl_hit 01*
[2024-02-17 03:16:48.143] dT: 15 Ail_ctrl_hit 01*
[2024-02-17 03:16:48.144] dT: 0 Ail cut----bail, Rud_ctl?true 01*
[2024-02-17 03:17:45.721] dT: 1738 Rud_ctrl_hit 03*
[2024-02-17 03:17:45.721] dT: 0 Rud_cut----bail, Ail_ctl?false 03*
[2024-02-17 03:17:50.340] dT: 153 Rud_ctrl_hit 03*
[2024-02-17 03:17:50.340] dT: 0 Rud_cut----bail, Ail_ctl?false 03*
[2024-02-17 03:17:50.800] dT: 16 Ail_ctrl_hit 03*
[2024-02-17 03:17:50.800] dT: 0 Ail cut----bail, Rud_ctl?false 03*
[2024-02-17 03:17:51.704] dT: 30 Rud_ctrl_hit 03*
[2024-02-17 03:17:51.704] dT: 0 Rud_cut----bail, Ail_ctl?false 03*