diff --git a/megamek/src/megamek/common/Aero.java b/megamek/src/megamek/common/Aero.java index 7d7f30e0793..e1525ad97d5 100644 --- a/megamek/src/megamek/common/Aero.java +++ b/megamek/src/megamek/common/Aero.java @@ -143,8 +143,6 @@ public String[] getLocationNames() { * applied before the attack resolves. */ private int altLossThisRound = 0; - private boolean avionicsHitThisRound = false; - private boolean controlHitThisRound = false; private boolean spheroid = false; @@ -761,24 +759,6 @@ public void setAvionicsHits(int hits) { avionicsHits = hits; } - @Override - public boolean isAvionicsHitThisRound() { - return avionicsHitThisRound; - } - - @Override - public void setAvionicsHitThisRound(boolean hit) { - avionicsHitThisRound = hit; - } - - public boolean isControlHitThisRound() { - return controlHitThisRound; - } - - public void setControlHitThisRound(boolean hit) { - controlHitThisRound = hit; - } - public boolean isGearHit() { return gearHit; } @@ -1053,8 +1033,6 @@ public void newRound(int roundNumber) { setWhoFirst(); resetAltLossThisRound(); - setAvionicsHitThisRound(false); - setControlHitThisRound(false); // Reset usedInternalBombs setUsedInternalBombs(0); diff --git a/megamek/src/megamek/common/IAero.java b/megamek/src/megamek/common/IAero.java index 8896d30d431..f69fb6fd0ab 100644 --- a/megamek/src/megamek/common/IAero.java +++ b/megamek/src/megamek/common/IAero.java @@ -107,10 +107,6 @@ public interface IAero { int getAvionicsHits(); - boolean isAvionicsHitThisRound(); - - void setAvionicsHitThisRound(boolean hit); - int getSensorHits(); int getFCSHits(); diff --git a/megamek/src/megamek/common/LandAirMech.java b/megamek/src/megamek/common/LandAirMech.java index 569b187bb80..eb794082c07 100644 --- a/megamek/src/megamek/common/LandAirMech.java +++ b/megamek/src/megamek/common/LandAirMech.java @@ -126,7 +126,6 @@ public String[] getLocationAbbrs() { private int straightMoves = 0; private int altLoss = 0; private int altLossThisRound = 0; - private boolean avionicsHitThisRound = false; //Autoejection @@ -882,7 +881,6 @@ public void newRound(int roundNumber) { setWhoFirst(); resetAltLossThisRound(); - setAvionicsHitThisRound(false); } } @@ -1334,16 +1332,6 @@ public int getAvionicsHits() { return hits; } - @Override - public boolean isAvionicsHitThisRound() { - return avionicsHitThisRound; - } - - @Override - public void setAvionicsHitThisRound(boolean hit) { - avionicsHitThisRound = hit; - } - @Override public int getSensorHits() { return getBadCriticals(CriticalSlot.TYPE_SYSTEM, SYSTEM_SENSORS, LOC_HEAD); diff --git a/megamek/src/megamek/server/GameManager.java b/megamek/src/megamek/server/GameManager.java index 9700308e8fb..07d0d3a1e9b 100644 --- a/megamek/src/megamek/server/GameManager.java +++ b/megamek/src/megamek/server/GameManager.java @@ -57,6 +57,7 @@ import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Manages the Game and processes player actions. @@ -20102,18 +20103,22 @@ private Vector resolveControl(Entity e) { if (e.isUsingManAce()) { target.addModifier(-1, "maneuvering ace"); } - for (Enumeration j = game.getControlRolls(); j.hasMoreElements(); ) { - final PilotingRollData modifier = j.nextElement(); - if (modifier.getEntityId() != e.getId()) { - continue; - } - // found a roll, add it - rolls.addElement(modifier); - if (reasons.length() > 0) { - reasons.append("; "); - } - reasons.append(modifier.getCumulativePlainDesc()); - target.append(modifier); + if (game.getOptions().booleanOption(OptionsConstants.ADVAERORULES_ATMOSPHERIC_CONTROL)) { + resolveControlWithAdvAtmospheric(e, target, rolls, reasons); + } else { + for (Enumeration j = game.getControlRolls(); j.hasMoreElements(); ) { + final PilotingRollData modifier = j.nextElement(); + if (modifier.getEntityId() != e.getId()) { + continue; + } + // found a roll, add it + rolls.addElement(modifier); + if (!reasons.isEmpty()) { + reasons.append("; "); + } + reasons.append(modifier.getCumulativePlainDesc()); + target.append(modifier); + } } // any rolls needed? if (!rolls.isEmpty()) { @@ -20279,6 +20284,44 @@ private Vector resolveControl(Entity e) { return vReport; } + void resolveControlWithAdvAtmospheric(Entity e, PilotingRollData target, Vector rolls, StringBuilder reasons) { + // The August 2024 errata changed this rule to only trigger one control roll per + // round regardless of how many crits or thresholds occurred. As a result, the rolls + // need to be combined here at the end phase because not all the information is known + // when the individual rolls are first added throughout the round and previously added + // rolls can't easily be modified. + PilotingRollData atmosphericControlRoll = null; + for (Enumeration j = game.getControlRolls(); j.hasMoreElements(); ) { + final PilotingRollData modifier = j.nextElement(); + if (modifier.getEntityId() != e.getId()) { + continue; + } + if (Stream.of("threshold exceeded", "avionics hit", "critical hit").anyMatch(s -> modifier.getDesc().contains(s))) { + if (atmosphericControlRoll == null) { + atmosphericControlRoll = modifier; + } else { + // Modify the description of the pending atmospheric control roll instead of adding another one + atmosphericControlRoll.addModifier(0, modifier.getDesc(), true); + } + } else { + // Not an atmospheric control roll under the new rules, so treat normally + rolls.addElement(modifier); + if (!reasons.isEmpty()) { + reasons.append("; "); + } + reasons.append(modifier.getCumulativePlainDesc()); + target.append(modifier); + } + } + if (atmosphericControlRoll != null) { + rolls.addElement(atmosphericControlRoll); + if (!reasons.isEmpty()) { + reasons.append("; "); + } + reasons.append(atmosphericControlRoll.getCumulativePlainDesc()); + } + } + /** * Check all aircraft that may have used internal bomb bays for incidental explosions * caused by ground fire. @@ -24044,7 +24087,6 @@ private Vector applyMechSystemCritical(Entity en, int loc, CriticalSlot break; case LandAirMech.LAM_AVIONICS: if (en.getConversionMode() == LandAirMech.CONV_MODE_FIGHTER) { - ((LandAirMech)en).setAvionicsHitThisRound(true); if (en.isPartOfFighterSquadron()) { game.addControlRoll(new PilotingRollData( en.getTransportId(), 1, "avionics hit")); @@ -24343,7 +24385,6 @@ private Vector applyAeroCritical(Aero aero, int loc, CriticalSlot cs, in r.subject = aero.getId(); reports.add(r); aero.setAvionicsHits(aero.getAvionicsHits() + 1); - aero.setAvionicsHitThisRound(true); if (aero.isPartOfFighterSquadron()) { game.addControlRoll(new PilotingRollData( aero.getTransportId(), 1, "avionics hit")); @@ -24360,7 +24401,6 @@ private Vector applyAeroCritical(Aero aero, int loc, CriticalSlot cs, in r = new Report(9115); r.subject = aero.getId(); reports.add(r); - aero.setControlHitThisRound(true); if (aero.isPartOfFighterSquadron()) { game.addControlRoll(new PilotingRollData( aero.getTransportId(), 1, "critical hit"));