diff --git a/megamek/build.gradle b/megamek/build.gradle
index eb97a2ba420..6f8528ee265 100644
--- a/megamek/build.gradle
+++ b/megamek/build.gradle
@@ -46,7 +46,7 @@ dependencies {
mainClassName = 'megamek.MegaMek'
ext {
- mmJvmOptions = ['-Xmx2048m', '--add-opens', 'java.base/java.util=ALL-UNNAMED', '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED']
+ mmJvmOptions = ['-Xmx4096m', '--add-opens', 'java.base/java.util=ALL-UNNAMED', '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED', '-Dsun.awt.disablegrab=true']
data = 'data'
unitFiles = "${data}/mechfiles"
rats = "${data}/rat"
@@ -101,12 +101,12 @@ task equipmentList(type: JavaExec, dependsOn: jar) {
task copyFiles(type: Copy) {
description = 'Stages files that are to be copied into the distribution.'
-
+
dependsOn officialUnitList
dependsOn equipmentList
-
+
from projectDir
-
+
include "${data}/**"
include "${docs}/**"
include "${mmconf}/**"
@@ -116,9 +116,9 @@ task copyFiles(type: Copy) {
exclude { it.file.isDirectory() && (it.file in file(unitFiles).listFiles()) }
exclude "${rats}/**"
include "${userdata}/"
-
+
into fileStagingDir
-
+
inputs.dir "${data}"
inputs.dir "${docs}"
inputs.dir "${mmconf}"
@@ -176,7 +176,7 @@ task stageFiles {
dependsOn unitFilesZip
dependsOn ratZip
dependsOn deleteAtlasedImages
-
+
doLast {
mkdir "${fileStagingDir}/${log}"
}
@@ -249,7 +249,7 @@ createExe {
new File("${buildDir}/${outputDir}/${iniFile}").text = """# Launch4j runtime config
# you can add arguments here that will be processed by the JVM at runtime
${project.ext.mmJvmOptions.join('\n')}
-"""
+"""
}
}
@@ -320,7 +320,7 @@ task buildFromRepo (type: GradleBuild) {
description = 'Assembles the distribution packages in the clean repository copy'
group = 'distribution'
dependsOn cloneMMRepo
-
+
dir = "${mmRepoDir}"
tasks = [ ':megamek:assembleDist' ]
}
@@ -329,7 +329,7 @@ task release (type: Copy) {
description = 'Builds the release packages from the repository and copies them into the project build directory'
group = 'distribution'
dependsOn buildFromRepo
-
+
from (buildFromRepo)
into "${distributionDir}"
}
diff --git a/megamek/i18n/megamek/client/messages.properties b/megamek/i18n/megamek/client/messages.properties
index a79527a4506..ce14a7f0307 100644
--- a/megamek/i18n/megamek/client/messages.properties
+++ b/megamek/i18n/megamek/client/messages.properties
@@ -3950,6 +3950,7 @@ WeaponAttackAction.AttackerNotReady=Attacker is in no condition to fire weapons.
WeaponAttackAction.AttackerTooHigh=attacker is too high.
WeaponAttackAction.BusyAltBombing=Already altitude bombing.
WeaponAttackAction.BusyDiveBombing=Already dive bombing.
+WeaponAttackAction.AlreadyUsedMaxInternalBombs=Already used maximum internal bombs (6).
WeaponAttackAction.BusyLayingMines=Can't fire weapons when laying mines.
WeaponAttackAction.BusySpaceBombing=Already space bombing.
WeaponAttackAction.CantShootAndFastMove=Infantry fast moved this turn and so can not shoot.
diff --git a/megamek/i18n/megamek/common/messages.properties b/megamek/i18n/megamek/common/messages.properties
index 05eed7b3bfb..f335a550587 100644
--- a/megamek/i18n/megamek/common/messages.properties
+++ b/megamek/i18n/megamek/common/messages.properties
@@ -311,7 +311,8 @@ PlanetaryConditions.Indicator.Gravity.Normal=\u23AF
PlanetaryConditions.Indicator.Gravity.High=\u2B73
PlanetaryConditions.Indicator.EMI.true=\u2301
PlanetaryConditions.Indicator.EMI.false=\u2312
-UnitType.Aero=Aerospace Fighter
+UnitType.Aero=Aerospace
+UnitType.AeroSpaceFighter=Aerospace Fighter
UnitType.BattleArmor=Battle Armor
UnitType.Conventional\ Fighter=Conventional Fighter
UnitType.Dropship=Dropship
diff --git a/megamek/i18n/megamek/common/options/messages.properties b/megamek/i18n/megamek/common/options/messages.properties
index 894be944f70..c7d9c1292f9 100644
--- a/megamek/i18n/megamek/common/options/messages.properties
+++ b/megamek/i18n/megamek/common/options/messages.properties
@@ -826,7 +826,7 @@ QuirksInfo.option.good_rep_2.description=Unit costs 25% more C-bills.\nincluded
QuirksInfo.option.hyper_actuator.displayableName=Hyper-Extending Actuators
QuirksInfo.option.hyper_actuator.description=This unit can flip arms,\neven with lower arm and hand actuators. (SO pg 194)
QuirksInfo.option.internal_bomb.displayableName=Internal Bomb Bay
-QuirksInfo.option.internal_bomb.description=No game effect,\ncurrently. (SO pg 195)
+QuirksInfo.option.internal_bomb.description=Allows some units to utilize cargo space as bomb bays, but risk internal explosions. (SO pg 195)
QuirksInfo.option.low_profile.displayableName=Narrow/Low Profile
QuirksInfo.option.low_profile.description=This unit is may take less damage because of a narrow/low profile. (BMM pg 85)
QuirksInfo.option.imp_com.displayableName=Improved Communications
diff --git a/megamek/i18n/megamek/common/report-messages.properties b/megamek/i18n/megamek/common/report-messages.properties
index 9b8446dc4d3..68f412919fd 100755
--- a/megamek/i18n/megamek/common/report-messages.properties
+++ b/megamek/i18n/megamek/common/report-messages.properties
@@ -726,6 +726,15 @@
5543=success!
5550=External heat reduced due to intact heat-dissipating armor!
5560= takes over as of ().
+5600=Bomb Bay Explosions-------------------
+5601= () took ground fire damage while dropping internal bay bombs.
+5602= () must roll under + to avoid bomb bay explosion, rolls .
+5603=\ () takes damage when remaining bombs explode!
+5604=\ () avoids bomb bay explosion; internal bombs remaining.
+5605=\ () suffers a critical Cargo hit;
+5606=player must choose bombs to be destroyed.
+5607=bot loses bombs.
+5608= () Internal Bomb Bay + Cargo critical: Damage exceeds remaining bombs; all bombs destroyed.
#6000's -- Damage Related
6005=\ no effect.
diff --git a/megamek/src/megamek/MegaMek.java b/megamek/src/megamek/MegaMek.java
index 1160d109f68..76d7c1ea9a6 100644
--- a/megamek/src/megamek/MegaMek.java
+++ b/megamek/src/megamek/MegaMek.java
@@ -356,4 +356,4 @@ public static void initializeSuiteGraphicalSetups(final String currentProject) {
// Setup Button Order Preferences
ButtonOrderPreferences.getInstance().setButtonPriorities();
}
-}
\ No newline at end of file
+}
diff --git a/megamek/src/megamek/client/bot/princess/ArtilleryTargetingControl.java b/megamek/src/megamek/client/bot/princess/ArtilleryTargetingControl.java
index fcf39db98da..a630e9f2185 100644
--- a/megamek/src/megamek/client/bot/princess/ArtilleryTargetingControl.java
+++ b/megamek/src/megamek/client/bot/princess/ArtilleryTargetingControl.java
@@ -449,8 +449,14 @@ public static double evaluateIncomingArtilleryDamage(Coords coords, Princess ope
if ((aaa.getTurnsTilHit() == 0) && (aaa.getTarget(operator.getGame()) != null)) {
// damage for artillery weapons is, for some reason, derived from the weapon type's rack size
+ int damage = 0;
Mounted weapon = aaa.getEntity(operator.getGame()).getEquipment(aaa.getWeaponId());
- int damage = ((WeaponType) weapon.getType()).getRackSize();
+ if (weapon.getType() instanceof BombType){
+ damage = (weapon.getExplosionDamage());
+ } else {
+ damage = ((WeaponType) weapon.getType()).getRackSize();
+ }
+
// distance from given coordinates reduces damage
Coords attackDestination = aaa.getTarget(operator.getGame()).getPosition();
diff --git a/megamek/src/megamek/client/bot/princess/FireControl.java b/megamek/src/megamek/client/bot/princess/FireControl.java
index 2a22d5c578d..76d1981f5d7 100644
--- a/megamek/src/megamek/client/bot/princess/FireControl.java
+++ b/megamek/src/megamek/client/bot/princess/FireControl.java
@@ -1439,7 +1439,7 @@ WeaponFireInfo buildWeaponFireInfo(final Entity shooter,
final boolean assumeUnderFlightPath,
final boolean guessToHit) {
return new WeaponFireInfo(shooter, flightPath, target, targetState,
- weapon, game, assumeUnderFlightPath, guessToHit, owner, new int[0]);
+ weapon, game, assumeUnderFlightPath, guessToHit, owner, null);
}
/**
@@ -1465,9 +1465,9 @@ private WeaponFireInfo buildWeaponFireInfo(final Entity shooter,
final Game game,
final boolean assumeUnderFlightPath,
final boolean guessToHit,
- final int[] bombPayload) {
+ final HashMap bombPayloads) {
return new WeaponFireInfo(shooter, flightPath, target, targetState,
- weapon, game, assumeUnderFlightPath, guessToHit, owner, bombPayload);
+ weapon, game, assumeUnderFlightPath, guessToHit, owner, bombPayloads);
}
/**
@@ -1694,11 +1694,22 @@ private FiringPlan getDiveBombPlan(final Entity shooter,
while (weaponIter.hasNext()) {
final Mounted weapon = weaponIter.next();
if (weapon.getType().hasFlag(WeaponType.F_DIVE_BOMB)) {
- final int[] bombPayload = new int[BombType.B_NUM];
+ final HashMap bombPayloads = new HashMap();
+ bombPayloads.put("internal", new int[BombType.B_NUM]);
+ bombPayloads.put("external", new int[BombType.B_NUM]);
+
// load up all droppable bombs, yeah baby! Mix thunder bombs and infernos 'cause why the hell not.
// seriously, though, TODO: more intelligent bomb drops
for (final Mounted bomb : shooter.getBombs(BombType.F_GROUND_BOMB)) {
- bombPayload[((BombType) bomb.getType()).getBombType()]++;
+ int bType = ((BombType) bomb.getType()).getBombType();
+ if (bomb.isInternalBomb()) {
+ // Can only drop 6 internal bombs in one turn.
+ if (bombPayloads.get("internal")[bType] < 6) {
+ bombPayloads.get("internal")[bType]++;
+ }
+ } else {
+ bombPayloads.get("external")[bType]++;
+ }
}
final WeaponFireInfo diveBomb = buildWeaponFireInfo(shooter,
@@ -1709,7 +1720,7 @@ private FiringPlan getDiveBombPlan(final Entity shooter,
game,
passedOverTarget,
guess,
- bombPayload);
+ bombPayloads);
diveBombPlan.add(diveBomb);
}
}
diff --git a/megamek/src/megamek/client/bot/princess/PathRanker.java b/megamek/src/megamek/client/bot/princess/PathRanker.java
index a56eb5d8cc8..a0fbb9dfcb3 100644
--- a/megamek/src/megamek/client/bot/princess/PathRanker.java
+++ b/megamek/src/megamek/client/bot/princess/PathRanker.java
@@ -35,7 +35,7 @@ public abstract class PathRanker implements IPathRanker {
// TODO: Introduce PathRankerCacheHelper class that contains "global" path ranker state
// TODO: Introduce FireControlCacheHelper class that contains "global" Fire Control state
// PathRanker classes should be pretty stateless, except pointers to princess and such
-
+
/**
* The possible path ranker types.
* If you're adding a new one, add it here then make sure to add it to Princess.InitializePathRankers
@@ -45,7 +45,7 @@ public enum PathRankerType {
Infantry,
NewtonianAerospace
}
-
+
private Princess owner;
public PathRanker(Princess princess) {
@@ -67,7 +67,7 @@ public ArrayList rankPaths(List movePaths, Game game, int
// the cached path probability data is really only relevant for one iteration through this method
getPathRankerState().getPathSuccessProbabilities().clear();
-
+
// Let's try to whittle down this list.
List validPaths = validatePaths(movePaths, game, maxRange, fallTolerance);
LogManager.getLogger().debug("Validated " + validPaths.size() + " out of " + movePaths.size() + " possible paths.");
@@ -75,46 +75,53 @@ public ArrayList rankPaths(List movePaths, Game game, int
Coords allyCenter = calcAllyCenter(movePaths.get(0).getEntity().getId(), friends, game);
ArrayList returnPaths = new ArrayList<>(validPaths.size());
- final BigDecimal numberPaths = new BigDecimal(validPaths.size());
- BigDecimal count = BigDecimal.ZERO;
- BigDecimal interval = new BigDecimal(5);
-
- boolean pathsHaveExpectedDamage = false;
-
- for (MovePath path : validPaths) {
- count = count.add(BigDecimal.ONE);
-
- RankedPath rankedPath = rankPath(path, game, maxRange, fallTolerance, enemies, allyCenter);
-
- returnPaths.add(rankedPath);
-
- // we want to keep track of if any of the paths we've considered have some kind of damage potential
- pathsHaveExpectedDamage |= (rankedPath.getExpectedDamage() > 0);
-
- BigDecimal percent = count.divide(numberPaths, 2, RoundingMode.DOWN).multiply(new BigDecimal(100))
- .round(new MathContext(0, RoundingMode.DOWN));
- if (percent.compareTo(interval) >= 0) {
- if (LogManager.getLogger().getLevel().isLessSpecificThan(Level.INFO)) {
- getOwner().sendChat("... " + percent.intValue() + "% complete.");
+
+ try {
+ final BigDecimal numberPaths = new BigDecimal(validPaths.size());
+ BigDecimal count = BigDecimal.ZERO;
+ BigDecimal interval = new BigDecimal(5);
+
+ boolean pathsHaveExpectedDamage = false;
+
+ for (MovePath path : validPaths) {
+ count = count.add(BigDecimal.ONE);
+
+ RankedPath rankedPath = rankPath(path, game, maxRange, fallTolerance, enemies, allyCenter);
+
+ returnPaths.add(rankedPath);
+
+ // we want to keep track of if any of the paths we've considered have some kind of damage potential
+ pathsHaveExpectedDamage |= (rankedPath.getExpectedDamage() > 0);
+
+ BigDecimal percent = count.divide(numberPaths, 2, RoundingMode.DOWN).multiply(new BigDecimal(100))
+ .round(new MathContext(0, RoundingMode.DOWN));
+ if (percent.compareTo(interval) >= 0) {
+ if (LogManager.getLogger().getLevel().isLessSpecificThan(Level.INFO)) {
+ getOwner().sendChat("... " + percent.intValue() + "% complete.");
+ }
+ interval = percent.add(new BigDecimal(5));
}
- interval = percent.add(new BigDecimal(5));
}
+
+ Entity mover = movePaths.get(0).getEntity();
+ UnitBehavior behaviorTracker = getOwner().getUnitBehaviorTracker();
+ boolean noDamageButCanDoDamage = !pathsHaveExpectedDamage
+ && (FireControl.getMaxDamageAtRange(mover, 1, false, false) > 0);
+
+ // if we're trying to fight, but aren't going to be doing any damage no matter how we move
+ // then let's try to get closer
+ if (noDamageButCanDoDamage
+ && (behaviorTracker.getBehaviorType(mover, getOwner()) == BehaviorType.Engaged)) {
+ behaviorTracker.overrideBehaviorType(mover, BehaviorType.MoveToContact);
+ return rankPaths(getOwner().getMovePathsAndSetNecessaryTargets(mover, true),
+ game, maxRange, fallTolerance, enemies, friends);
+ }
+ } catch (Exception ignored) {
+ LogManager.getLogger().error(ignored.toString());
+ return returnPaths;
}
-
- Entity mover = movePaths.get(0).getEntity();
- UnitBehavior behaviorTracker = getOwner().getUnitBehaviorTracker();
- boolean noDamageButCanDoDamage = !pathsHaveExpectedDamage
- && (FireControl.getMaxDamageAtRange(mover, 1, false, false) > 0);
-
- // if we're trying to fight, but aren't going to be doing any damage no matter how we move
- // then let's try to get closer
- if (noDamageButCanDoDamage
- && (behaviorTracker.getBehaviorType(mover, getOwner()) == BehaviorType.Engaged)) {
- behaviorTracker.overrideBehaviorType(mover, BehaviorType.MoveToContact);
- return rankPaths(getOwner().getMovePathsAndSetNecessaryTargets(mover, true),
- game, maxRange, fallTolerance, enemies, friends);
- }
-
+
+
return returnPaths;
}
@@ -138,7 +145,7 @@ private List validatePaths(List startingPathList, Game game,
boolean isAirborneAeroOnGroundMap = mover.isAirborneAeroOnGroundMap();
boolean needToUnjamRAC = mover.canUnjamRAC();
int walkMP = mover.getWalkMP();
-
+
for (MovePath path : startingPathList) {
// just in case
if ((path == null) || !path.isMoveLegal()) {
@@ -191,7 +198,7 @@ private List validatePaths(List startingPathList, Game game,
msg.append("\n\tINADVISABLE: Want to unjam autocannon but path involves running or jumping");
continue;
}
-
+
// If all the above checks have passed, this is a valid path.
msg.append("\n\tVALID.");
returnPaths.add(path);
@@ -210,7 +217,7 @@ private List validatePaths(List startingPathList, Game game,
/**
* Returns the best path of a list of ranked paths.
- *
+ *
* @param ps The list of ranked paths to process
* @return "Best" out of those paths
*/
@@ -231,7 +238,7 @@ public void initUnitTurn(Entity unit, Game game) {
public Targetable findClosestEnemy(Entity me, Coords position, Game game) {
return findClosestEnemy(me, position, game, true);
}
-
+
/**
* Find the closest enemy to a unit with a path
*/
@@ -245,7 +252,7 @@ public Targetable findClosestEnemy(Entity me, Coords position, Game game,
// Skip airborne aero units as they're further away than they seem and hard to catch.
// Also, skip withdrawing enemy bot units, to avoid humping disabled tanks and ejected
// MechWarriors
- if (e.isAirborneAeroOnGroundMap() ||
+ if (e.isAirborneAeroOnGroundMap() ||
getOwner().getHonorUtil().isEnemyBroken(e.getId(), e.getOwnerId(),
getOwner().getForcedWithdrawal())) {
continue;
@@ -263,7 +270,7 @@ public Targetable findClosestEnemy(Entity me, Coords position, Game game,
closest = e;
}
}
-
+
// if specified, we also consider strategic targets
if (includeStrategicTargets) {
for (Targetable t : getOwner().getFireControlState().getAdditionalTargets()) {
@@ -274,7 +281,7 @@ public Targetable findClosestEnemy(Entity me, Coords position, Game game,
}
}
}
-
+
return closest;
}
@@ -286,7 +293,7 @@ protected double getMovePathSuccessProbability(MovePath movePath, StringBuilder
if (getPathRankerState().getPathSuccessProbabilities().containsKey(movePath.getKey())) {
return getPathRankerState().getPathSuccessProbabilities().get(movePath.getKey());
}
-
+
MovePath pathCopy = movePath.clone();
List pilotingRolls = getPSRList(pathCopy);
double successProbability = 1.0;
@@ -332,7 +339,7 @@ protected double getMovePathSuccessProbability(MovePath movePath, StringBuilder
msg.append("\n\t\tTotal = ").append(NumberFormat.getPercentInstance().format(successProbability));
getPathRankerState().getPathSuccessProbabilities().put(movePath.getKey(), successProbability);
-
+
return successProbability;
}
@@ -419,7 +426,7 @@ private boolean willBuildingCollapse(MovePath path, Game game) {
if (path.getEntity().isAero() || path.getEntity().hasETypeFlag(Entity.ETYPE_VTOL)) {
return false;
}
-
+
// If we're jumping onto a building, make sure it can support our weight.
if (path.isJumping()) {
final Coords finalCoords = path.getFinalCoords();
@@ -505,7 +512,7 @@ private boolean willBuildingCollapse(MovePath path, Game game) {
protected Princess getOwner() {
return owner;
}
-
+
/**
* Convenience property to access bot-wide state information.
* @return the owner's path ranker state
diff --git a/megamek/src/megamek/client/bot/princess/WeaponFireInfo.java b/megamek/src/megamek/client/bot/princess/WeaponFireInfo.java
index 93e57bc29de..e0382971585 100644
--- a/megamek/src/megamek/client/bot/princess/WeaponFireInfo.java
+++ b/megamek/src/megamek/client/bot/princess/WeaponFireInfo.java
@@ -27,6 +27,7 @@
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
/**
@@ -80,7 +81,7 @@ protected WeaponFireInfo(final Princess owner) {
final Game game,
final boolean guess,
final Princess owner) {
- this(shooter, null, null, target, null, weapon, game, false, guess, owner, new int[0]);
+ this(shooter, null, null, target, null, weapon, game, false, guess, owner, null);
}
/**
@@ -102,7 +103,7 @@ protected WeaponFireInfo(final Princess owner) {
final Game game,
final boolean guess,
final Princess owner) {
- this(shooter, shooterState, null, target, targetState, weapon, game, false, guess, owner, new int[0]);
+ this(shooter, shooterState, null, target, targetState, weapon, game, false, guess, owner, null);
}
/**
@@ -128,8 +129,8 @@ protected WeaponFireInfo(final Princess owner) {
final boolean assumeUnderFlightPath,
final boolean guess,
final Princess owner,
- final int[] bombPayload) {
- this(shooter, null, shooterPath, target, targetState, weapon, game, assumeUnderFlightPath, guess, owner, bombPayload);
+ final HashMap bombPayloads) {
+ this(shooter, null, shooterPath, target, targetState, weapon, game, assumeUnderFlightPath, guess, owner, bombPayloads);
}
/**
@@ -159,7 +160,7 @@ private WeaponFireInfo(final Entity shooter,
final boolean assumeUnderFlightPath,
final boolean guess,
final Princess owner,
- final int[] bombPayload) {
+ final HashMap bombPayloads) {
this.owner = owner;
setShooter(shooter);
@@ -168,7 +169,7 @@ private WeaponFireInfo(final Entity shooter,
setTargetState(targetState);
setWeapon(weapon);
setGame(game);
- initDamage(shooterPath, assumeUnderFlightPath, guess, bombPayload);
+ initDamage(shooterPath, assumeUnderFlightPath, guess, bombPayloads);
}
protected WeaponAttackAction getAction() {
@@ -276,7 +277,7 @@ shooterPath, getWeapon(), getGame(),
}
private ToHitData calcRealToHit(final WeaponAttackAction weaponAttackAction) {
- return weaponAttackAction.toHit(getGame(),
+ return weaponAttackAction.toHit(getGame(),
owner.getPrecognition().getECMInfo());
}
@@ -331,7 +332,7 @@ public double getExpectedDamage() {
}
WeaponAttackAction buildWeaponAttackAction() {
- if (!(getWeapon().getType().hasFlag(WeaponType.F_ARTILLERY)
+ if (!(getWeapon().getType().hasFlag(WeaponType.F_ARTILLERY)
|| (getWeapon().getType() instanceof CapitalMissileWeapon
&& Compute.isGroundToGround(shooter, target)))) {
return new WeaponAttackAction(getShooter().getId(), getTarget().getTargetType(), getTarget().getId(),
@@ -342,14 +343,14 @@ WeaponAttackAction buildWeaponAttackAction() {
}
}
- private WeaponAttackAction buildBombAttackAction(final int[] bombPayload) {
+ private WeaponAttackAction buildBombAttackAction(final HashMap bombPayloads) {
final WeaponAttackAction diveBomb = new WeaponAttackAction(getShooter().getId(),
getTarget().getTargetType(),
getTarget().getId(),
getShooter().getEquipmentNum(getWeapon()));
-
- diveBomb.setBombPayload(bombPayload);
-
+
+ diveBomb.setBombPayloads(bombPayloads);
+
return diveBomb;
}
@@ -358,7 +359,7 @@ private WeaponAttackAction buildBombAttackAction(final int[] bombPayload) {
if (weapon.isGroundBomb()) {
return computeExpectedBombDamage(getShooter(), weapon, getTarget().getPosition());
}
-
+
// bay weapons require special consideration, by looping through all weapons and adding up the damage
// A bay's weapons may have different ranges, most noticeable in laser bays, where the damage potential
// varies with distance to target.
@@ -370,9 +371,9 @@ private WeaponAttackAction buildBombAttackAction(final int[] bombPayload) {
int maxRange = game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_RANGE)
? weaponType.getExtremeRange() : weaponType.getLongRange();
int targetDistance = getShooter().getPosition().distance(getTarget().getPosition());
-
+
// if the particular weapon is within range or we're an aircraft strafing a ground unit
- // then we can count it. Otherwise, it's not going to contribute to damage, and we want
+ // then we can count it. Otherwise, it's not going to contribute to damage, and we want
// to avoid grossly overestimating damage.
if (targetDistance <= maxRange || shooter.isAirborne() && !target.isAirborne()) {
bayDamage += weaponType.getDamage();
@@ -390,27 +391,27 @@ private WeaponAttackAction buildBombAttackAction(final int[] bombPayload) {
}
// artillery and cluster table use the rack size as the base damage amount
- // a little inaccurate, but better than ignoring those weapons entirely
+ // a little inaccurate, but better than ignoring those weapons entirely
if ((weaponType.getDamage() == WeaponType.DAMAGE_BY_CLUSTERTABLE) ||
(weaponType.getDamage() == WeaponType.DAMAGE_ARTILLERY)) {
return weaponType.getRackSize();
}
- // infantry weapons use number of troopers multiplied by weapon damage,
+ // infantry weapons use number of troopers multiplied by weapon damage,
// with # troopers counting as 1 for support vehicles
if ((weaponType.getDamage() == WeaponType.DAMAGE_VARIABLE) &&
(weaponType instanceof InfantryWeapon)) {
- int numTroopers = (shooter instanceof Infantry) ?
+ int numTroopers = (shooter instanceof Infantry) ?
((Infantry) shooter).getShootingStrength() : 1;
return InfantryWeaponHandler.calculateBaseDamage(shooter, weapon, weaponType) * numTroopers;
}
-
+
// this is a special case - if we're considering hitting a swarmed target
// that's basically our only option
if (weaponType.getInternalName() == Infantry.SWARM_WEAPON_MEK) {
return 1;
}
-
+
if (getTarget() instanceof Entity) {
double dmg = Compute.getExpectedDamage(getGame(), getAction(),
true, owner.getPrecognition().getECMInfo());
@@ -419,10 +420,10 @@ private WeaponAttackAction buildBombAttackAction(final int[] bombPayload) {
}
return dmg;
}
-
+
return weaponType.getDamage();
}
-
+
/**
* Compute the heat output by firing a given weapon.
* Contains special logic for bay weapons when using individual bay heat.
@@ -441,13 +442,13 @@ int computeHeat(Mounted weapon) {
WeaponType weaponType = (WeaponType) bayWeapon.getType();
bayHeat += weaponType.getHeat();
}
-
+
return bayHeat;
} else {
return weapon.getType().getHeat();
}
}
-
+
/**
* Worker function to compute expected bomb damage given the shooter
* @param shooter The unit making the attack.
@@ -458,35 +459,35 @@ int computeHeat(Mounted weapon) {
private double computeExpectedBombDamage(final Entity shooter, final Mounted weapon,
final Coords bombedHex) {
double damage = 0D; //lol double damage I wish
-
+
// for dive attacks, we can pretty much assume that we're going to drop everything we've got on the poor scrubs in this hex
if (weapon.getType().hasFlag(WeaponType.F_DIVE_BOMB)) {
for (final Mounted bomb : shooter.getBombs(BombType.F_GROUND_BOMB)) {
final int damagePerShot = ((BombType) bomb.getType()).getDamagePerShot();
-
+
// some bombs affect a blast radius, so we take that into account
final List affectedHexes = new ArrayList<>();
-
- int blastRadius = BombType.getBombBlastRadius(bomb.getType().getInternalName());
+
+ int blastRadius = BombType.getBombBlastRadius(bomb.getType().getInternalName());
for (int radius = 0; radius <= blastRadius; radius++) {
affectedHexes.addAll(bombedHex.allAtDistance(radius));
}
-
+
// now we go through all affected hexes and add up the damage done
for (final Coords coords : affectedHexes) {
- for (final Entity currentVictim : game.getEntitiesVector(coords)) {
+ for (final Entity currentVictim : game.getEntitiesVector(coords)) {
if (currentVictim.getOwner().getTeam() != shooter.getOwner().getTeam()) {
damage += damagePerShot;
} else { // we prefer not to blow up friendlies if we can help it
damage -= damagePerShot;
- }
+ }
}
}
}
}
-
+
damage = damage * getProbabilityToHit();
-
+
return damage;
}
@@ -501,9 +502,9 @@ private double computeExpectedBombDamage(final Entity shooter, final Mounted wea
void initDamage(@Nullable final MovePath shooterPath,
final boolean assumeUnderFlightPath,
final boolean guess,
- final int[] bombPayload) {
+ final HashMap bombPayloads) {
boolean debugging = false;
-
+
final StringBuilder msg =
debugging ?
new StringBuilder("Initializing Damage for ").append(getShooter().getDisplayName())
@@ -513,12 +514,12 @@ void initDamage(@Nullable final MovePath shooterPath,
null;
// Set up the attack action and calculate the chance to hit.
- if ((null == bombPayload) || (0 == bombPayload.length)) {
+ if ((null == bombPayloads) || (0 == bombPayloads.get("external").length)) {
setAction(buildWeaponAttackAction());
} else {
- setAction(buildBombAttackAction(bombPayload));
+ setAction(buildBombAttackAction(bombPayloads));
}
-
+
if (!guess) {
setToHit(calcRealToHit(getWeaponAttackAction()));
} else if (null != shooterPath) {
@@ -539,13 +540,13 @@ void initDamage(@Nullable final MovePath shooterPath,
setExpectedDamageOnHit(0);
return;
}
-
+
if (debugging && getShooterState().hasNaturalAptGun()) {
msg.append("\n\tAttacker has Natural Aptitude Gunnery");
}
-
+
setProbabilityToHit(Compute.oddsAbove(getToHit().getValue(), getShooterState().hasNaturalAptGun()) / 100);
-
+
if (debugging) {
msg.append("\n\tHit Chance: ").append(LOG_PER.format(getProbabilityToHit()));
}
@@ -557,16 +558,16 @@ void initDamage(@Nullable final MovePath shooterPath,
if (!currentFireMode.equals(getWeapon().curMode().getName())) {
setUpdatedFiringMode(spinMode);
}
-
+
setHeat(computeHeat(weapon));
-
+
if (debugging) {
msg.append("\n\tHeat: ").append(getHeat());
}
setExpectedDamageOnHit(computeExpectedDamage());
setMaxDamage(getExpectedDamageOnHit());
-
+
if (debugging) {
msg.append("\n\tMax Damage: ").append(LOG_DEC.format(maxDamage));
}
@@ -637,7 +638,7 @@ void initDamage(@Nullable final MovePath shooterPath,
LogManager.getLogger().debug(msg.toString());
}
}
-
+
WeaponAttackAction getWeaponAttackAction() {
if (null != getAction()) {
return getAction();
@@ -677,7 +678,7 @@ String getDebugDescription() {
public Integer getUpdatedFiringMode() {
return updatedFiringMode;
}
-
+
public void setUpdatedFiringMode(int mode) {
updatedFiringMode = mode;
}
diff --git a/megamek/src/megamek/client/ratgenerator/AbstractUnitRecord.java b/megamek/src/megamek/client/ratgenerator/AbstractUnitRecord.java
index 45be0fd459b..27f4cdff6e6 100644
--- a/megamek/src/megamek/client/ratgenerator/AbstractUnitRecord.java
+++ b/megamek/src/megamek/client/ratgenerator/AbstractUnitRecord.java
@@ -135,6 +135,8 @@ public static int parseUnitType(String typeName) {
return UnitType.GUN_EMPLACEMENT;
case "Conventional Fighter":
return UnitType.CONV_FIGHTER;
+ case "AeroSpaceFighter":
+ return UnitType.AEROSPACEFIGHTER;
case "Aero":
return UnitType.AERO;
case "Small Craft":
diff --git a/megamek/src/megamek/client/ratgenerator/ForceDescriptor.java b/megamek/src/megamek/client/ratgenerator/ForceDescriptor.java
index 3707bc3f104..b89c4315272 100644
--- a/megamek/src/megamek/client/ratgenerator/ForceDescriptor.java
+++ b/megamek/src/megamek/client/ratgenerator/ForceDescriptor.java
@@ -538,10 +538,10 @@ public void generateLance(List subs) {
ModelRecord baseModel = null;
/* Generate base model using weight class of entire formation */
if (ut != null) {
- if (!(ut == UnitType.MEK || (ut == UnitType.AERO && subs.size() > 3))) {
+ if (!(ut == UnitType.MEK || (ut == UnitType.AEROSPACEFIGHTER && subs.size() > 3))) {
baseModel = subs.get(0).generate();
}
- if (ut == UnitType.AERO || ut == UnitType.CONV_FIGHTER) {
+ if (ut == UnitType.AEROSPACEFIGHTER || ut == UnitType.CONV_FIGHTER || ut == UnitType.AERO ) {
target -= 3;
}
if (roles.contains(MissionRole.ARTILLERY)) {
@@ -711,7 +711,7 @@ public void setUnit(ModelRecord unit) {
if (null == unitType) {
unitType = unit.getUnitType();
}
- if (((unitType == UnitType.MEK) || (unitType == UnitType.AERO)
+ if (((unitType == UnitType.MEK) || (unitType == UnitType.AEROSPACEFIGHTER)
|| (unitType == UnitType.TANK))
&& unit.isOmni()) {
flags.add("omni");
@@ -826,7 +826,7 @@ public void loadEntities(Ruleset.ProgressListener l, double progress) {
l.updateProgress(progress, "Loading entities");
}
}
-
+
/** Generates a force string for exporting these units to MUL / adding to the game. */
private String getForceString() {
var ancestors = new ArrayList();
@@ -955,7 +955,7 @@ public void assignCommanders() {
for (ForceDescriptor fd : subforces) {
movementModes.addAll(fd.getMovementModes());
if ((fd.getUnitType() == null ||
- !((UnitType.MEK == fd.getUnitType()) || (UnitType.AERO == fd.getUnitType())
+ !((UnitType.MEK == fd.getUnitType()) || (UnitType.AEROSPACEFIGHTER == fd.getUnitType())
|| (UnitType.TANK == fd.getUnitType()))) ||
!fd.getFlags().contains("omni")) {
isOmni = false;
@@ -989,7 +989,7 @@ public void assignCommanders() {
for (ForceDescriptor sub : subforces) {
if (sub.useWeightClass()) {
if (sub.getWeightClass() == null) {
- LogManager.getLogger().error("Weight class == null for "
+ LogManager.getLogger().error("Weight class == null for "
+ sub.getUnitType() + " with " + sub.getSubforces().size() + " subforces.");
} else {
wt += sub.getWeightClass();
@@ -1193,7 +1193,7 @@ private boolean useWeightClass(Integer ut) {
return ut != null &&
!(roles.contains(MissionRole.ARTILLERY) || roles.contains(MissionRole.MISSILE_ARTILLERY)) &&
(ut == UnitType.MEK ||
- ut == UnitType.AERO ||
+ ut == UnitType.AEROSPACEFIGHTER ||
ut == UnitType.TANK ||
ut == UnitType.BATTLE_ARMOR);
}
diff --git a/megamek/src/megamek/client/ui/swing/AdvancedSearchDialog.java b/megamek/src/megamek/client/ui/swing/AdvancedSearchDialog.java
index 969f484d794..94c69ebaec2 100644
--- a/megamek/src/megamek/client/ui/swing/AdvancedSearchDialog.java
+++ b/megamek/src/megamek/client/ui/swing/AdvancedSearchDialog.java
@@ -264,6 +264,7 @@ public void mouseClicked(MouseEvent e) {
unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.BATTLE_ARMOR));
unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.INFANTRY));
unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.PROTOMEK));
+ unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.AEROSPACEFIGHTER));
unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.AERO));
unitTypeModel.setSelectedItem(Messages.getString("MechSelectorDialog.All"));
@@ -1158,7 +1159,7 @@ public void setValueAt(Object value, int row, int col) {
/**
* A table model for displaying weapon types
*/
-
+
/**
* A table model for displaying equipment
*/
diff --git a/megamek/src/megamek/client/ui/swing/BombChoicePanel.java b/megamek/src/megamek/client/ui/swing/BombChoicePanel.java
index c0c2f8c6f53..e2b1a690253 100644
--- a/megamek/src/megamek/client/ui/swing/BombChoicePanel.java
+++ b/megamek/src/megamek/client/ui/swing/BombChoicePanel.java
@@ -13,15 +13,20 @@
*/
package megamek.client.ui.swing;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
+import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashMap;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+import javax.swing.border.TitledBorder;
import megamek.common.BombType;
import megamek.common.IBomber;
@@ -35,18 +40,25 @@ public class BombChoicePanel extends JPanel implements Serializable, ItemListene
private final boolean at2Nukes;
private final boolean allowAdvancedAmmo;
+ private boolean empty = false;
+
private static final long serialVersionUID = 483782753790544050L;
@SuppressWarnings("rawtypes")
- private JComboBox[] b_choices = new JComboBox[BombType.B_NUM];
- private JLabel[] b_labels = new JLabel[BombType.B_NUM];
- private int maxPoints = 0;
- private int maxSize = 0;
+ private JPanel interiorPanel;
+ private JPanel exteriorPanel;
+ private HashMap b_choices = new HashMap();
+ private HashMap b_labels = new HashMap();
+ private HashMap maxPoints = new HashMap();
+ private HashMap maxSize = new HashMap();
private int maxRows = (int) Math.ceil(BombType.B_NUM / 2.0);
-
+
//Variable for MekHQ functionality
private int[] typeMax = null;
+ private final String INTNAME = "Internal";
+ private final String EXTNAME = "External";
+
//private BombChoicePanel m_bombs;
//private JPanel panBombs = new JPanel();
@@ -54,51 +66,112 @@ public BombChoicePanel(IBomber bomber, boolean at2Nukes, boolean allowAdvancedAm
this.bomber = bomber;
this.at2Nukes = at2Nukes;
this.allowAdvancedAmmo = allowAdvancedAmmo;
+
+ initArrays();
initPanel();
}
+
//Constructor to call from MekHQ to pass in typeMax
public BombChoicePanel(IBomber bomber, boolean at2Nukes, boolean allowAdvancedAmmo, int[] typeMax) {
this.bomber = bomber;
this.at2Nukes = at2Nukes;
this.allowAdvancedAmmo = allowAdvancedAmmo;
this.typeMax = typeMax;
+
+ initArrays();
initPanel();
}
-
+
+ private void initArrays(){
+ // Initialize control arrays
+ b_choices.put(INTNAME, new JComboBox[BombType.B_NUM]);
+ b_choices.put(EXTNAME, new JComboBox[BombType.B_NUM]);
+ b_labels.put(INTNAME, new JLabel[BombType.B_NUM]);
+ b_labels.put(EXTNAME, new JLabel[BombType.B_NUM]);
+ maxSize.put(INTNAME, 0);
+ maxSize.put(EXTNAME, 0);
+ }
+
+ private int compileBombPoints(int[] choices) {
+ int currentPoints = 0;
+ for (int i = 0; i < choices.length; i++) {
+ currentPoints += choices[i] * BombType.getBombCost(i);
+ }
+ return currentPoints;
+ }
+
@SuppressWarnings("unchecked")
private void initPanel() {
- maxPoints = bomber.getMaxBombPoints();
- maxSize = bomber.getMaxBombSize();
- int[] bombChoices = bomber.getBombChoices();
-
- // how many bomb points am I currently using?
- int curBombPoints = 0;
- for (int i = 0; i < bombChoices.length; i++) {
- curBombPoints += bombChoices[i] * BombType.getBombCost(i);
+ maxPoints.put(INTNAME, bomber.getMaxIntBombPoints());
+ maxPoints.put(EXTNAME, bomber.getMaxExtBombPoints());
+
+ maxSize.put(INTNAME, bomber.getMaxIntBombSize());
+ maxSize.put(EXTNAME, bomber.getMaxExtBombSize());
+
+ int[] intBombChoices = bomber.getIntBombChoices();
+ int[] extBombChoices = bomber.getExtBombChoices();
+
+ int columns = (maxPoints.get(INTNAME) > 0 ? 1 : 0) + (maxPoints.get(EXTNAME) > 0 ? 1 : 0);
+ // Should not occur!
+ if (columns == 0){
+ empty = true;
+ return;
}
- int availBombPoints = bomber.getMaxBombPoints() - curBombPoints;
+
+ JPanel outer = new JPanel();
+ outer.setLayout(new GridLayout(0, columns));
+ TitledBorder titledBorder = new TitledBorder(new LineBorder(Color.blue), "Bombs");
+ Font font2 = new Font("Verdana", Font.BOLD + Font.ITALIC, 12);
+ titledBorder.setTitleFont(font2);
+ EmptyBorder emptyBorder = new EmptyBorder(10, 10, 10, 10);
+ CompoundBorder compoundBorder = new CompoundBorder(titledBorder, emptyBorder);
+ outer.setBorder(compoundBorder);
+
+ interiorPanel = initSubPanel(maxPoints.get(INTNAME) - compileBombPoints(intBombChoices), intBombChoices, INTNAME);
+ exteriorPanel = initSubPanel(maxPoints.get(EXTNAME) - compileBombPoints(extBombChoices), extBombChoices, EXTNAME);
+
+ if (maxPoints.get(INTNAME) != 0) {
+ outer.add(interiorPanel);
+ }
+ if (maxPoints.get(EXTNAME) != 0) {
+ outer.add(exteriorPanel);
+ }
+ add(outer);
+ }
+
+ private JPanel initSubPanel(int availBombPoints, int[] bombChoices, String title){
+
+ // Set up sub-panel
+ JPanel inner = new JPanel();
+ TitledBorder titledBorder = new TitledBorder(new LineBorder(Color.blue), title);
+ Font font3 = new Font("Verdana", Font.BOLD + Font.ITALIC, 10);
+ titledBorder.setTitleFont(font3);
+ EmptyBorder emptyBorder = new EmptyBorder(10, 10, 10, 10);
+ CompoundBorder compoundBorder = new CompoundBorder(titledBorder, emptyBorder);
+ inner.setBorder(compoundBorder);
GridBagLayout g = new GridBagLayout();
- setLayout(g);
+ inner.setLayout(g);
GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
int column = 0;
int row = 0;
for (int type = 0; type < BombType.B_NUM; type++) {
- b_labels[type] = new JLabel();
- b_choices[type] = new JComboBox();
+ b_labels.get(title)[type] = new JLabel();
+ b_choices.get(title)[type] = new JComboBox();
int maxNumBombs = Math.round(availBombPoints / BombType.getBombCost(type)) + bombChoices[type];
- if (BombType.getBombCost(type) > maxSize) {
+ if (BombType.getBombCost(type) > maxSize.get(title)) {
maxNumBombs = 0;
}
// somehow too many bombs were added
- if ((bombChoices[type] * BombType.getBombCost(type)) > maxSize) {
- bombChoices[type] = maxSize / BombType.getBombCost(type);
+ if ((bombChoices[type] * BombType.getBombCost(type)) > maxSize.get(title)) {
+ bombChoices[type] = maxSize.get(title) / BombType.getBombCost(type);
}
-
+
if (typeMax != null) {
if ((maxNumBombs > 0) && (maxNumBombs > typeMax[type])) {
maxNumBombs = typeMax[type];
@@ -113,23 +186,23 @@ private void initPanel() {
maxNumBombs = 0;
}
- if (maxNumBombs > maxSize) {
- maxNumBombs = maxSize;
+ if (maxNumBombs > maxSize.get(title)) {
+ maxNumBombs = maxSize.get(title);
}
for (int x = 0; x <= maxNumBombs; x++) {
- b_choices[type].addItem(Integer.toString(x));
+ b_choices.get(title)[type].addItem(Integer.toString(x));
}
- b_choices[type].setSelectedIndex(bombChoices[type]);
- b_labels[type].setText(BombType.getBombName(type));
- b_choices[type].addItemListener(this);
+ b_choices.get(title)[type].setSelectedIndex(bombChoices[type]);
+ b_labels.get(title)[type].setText(BombType.getBombName(type));
+ b_choices.get(title)[type].addItemListener(this);
if ((type == BombType.B_ALAMO) && !at2Nukes) {
- b_choices[type].setEnabled(false);
+ b_choices.get(title)[type].setEnabled(false);
}
if ((type > BombType.B_TAG) && !allowAdvancedAmmo) {
- b_choices[type].setEnabled(false);
+ b_choices.get(title)[type].setEnabled(false);
}
if (row >= maxRows) {
@@ -140,94 +213,114 @@ private void initPanel() {
c.gridx = column;
c.gridy = row;
c.anchor = GridBagConstraints.EAST;
- g.setConstraints(b_labels[type], c);
- add(b_labels[type]);
+ g.setConstraints(b_labels.get(title)[type], c);
+ inner.add(b_labels.get(title)[type]);
c.gridx = column + 1;
c.gridy = row;
c.anchor = GridBagConstraints.WEST;
- g.setConstraints(b_choices[type], c);
- add(b_choices[type]);
+ g.setConstraints(b_choices.get(title)[type], c);
+ inner.add(b_choices.get(title)[type]);
row++;
}
+ return inner;
}
@Override
@SuppressWarnings("unchecked")
public void itemStateChanged(ItemEvent ie) {
- int[] current = new int[BombType.B_NUM];
- int curPoints = 0;
- for (int type = 0; type < BombType.B_NUM; type++) {
- current[type] = b_choices[type].getSelectedIndex();
- curPoints += current[type] * BombType.getBombCost(type);
- }
+ for (String title: new String[]{INTNAME, EXTNAME}){
+ int[] current = new int[BombType.B_NUM];
+ int curPoints = 0;
+ for (int type = 0; type < BombType.B_NUM; type++) {
+ current[type] = b_choices.get(title)[type].getSelectedIndex();
+ curPoints += current[type] * BombType.getBombCost(type);
+ }
- int availBombPoints = maxPoints - curPoints;
+ int availBombPoints = maxPoints.get(title) - curPoints;
- for (int type = 0; type < BombType.B_NUM; type++) {
- b_choices[type].removeItemListener(this);
- b_choices[type].removeAllItems();
- int maxNumBombs = Math.round(availBombPoints / BombType.getBombCost(type)) + current[type];
+ for (int type = 0; type < BombType.B_NUM; type++) {
+ b_choices.get(title)[type].removeItemListener(this);
+ b_choices.get(title)[type].removeAllItems();
+ int maxNumBombs = Math.round(availBombPoints / BombType.getBombCost(type)) + current[type];
- if (typeMax != null) {
- if ((maxNumBombs > 0) && (maxNumBombs > typeMax[type])) {
- maxNumBombs = typeMax[type];
+ if (typeMax != null) {
+ if ((maxNumBombs > 0) && (maxNumBombs > typeMax[type])) {
+ maxNumBombs = typeMax[type];
+ }
}
- }
- if (current[type] > maxNumBombs) {
- maxNumBombs = current[type];
- }
+ if (current[type] > maxNumBombs) {
+ maxNumBombs = current[type];
+ }
- if (maxNumBombs < 0) {
- maxNumBombs = 0;
- }
+ if (maxNumBombs < 0) {
+ maxNumBombs = 0;
+ }
- if (maxNumBombs > maxSize) {
- maxNumBombs = maxSize;
- }
+ if (maxNumBombs > maxSize.get(title)) {
+ maxNumBombs = maxSize.get(title);
+ }
- for (int x = 0; x <= maxNumBombs; x++) {
- b_choices[type].addItem(Integer.toString(x));
+ for (int x = 0; x <= maxNumBombs; x++) {
+ b_choices.get(title)[type].addItem(Integer.toString(x));
+ }
+ b_choices.get(title)[type].setSelectedIndex(current[type]);
+ b_choices.get(title)[type].addItemListener(this);
}
- b_choices[type].setSelectedIndex(current[type]);
- b_choices[type].addItemListener(this);
}
}
public void applyChoice() {
+ // Return cleanly if bomber never had any capacity but e.g. Internal Bomb Bay tried add bomb capacity.
+ if (empty) {
+ return;
+ }
+
int[] choices = new int[BombType.B_NUM];
+ // Internal bombs
for (int type = 0; type < BombType.B_NUM; type++) {
- choices[type] = b_choices[type].getSelectedIndex();
+ choices[type] = b_choices.get(INTNAME)[type].getSelectedIndex();
}
-
- bomber.setBombChoices(choices);
+ bomber.setIntBombChoices(choices);
+ // External bombs
+ for (int type = 0; type < BombType.B_NUM; type++) {
+ choices[type] = b_choices.get(EXTNAME)[type].getSelectedIndex();
+ }
+ bomber.setExtBombChoices(choices);
}
public int[] getChoice() {
int[] choices = new int[BombType.B_NUM];
+ Arrays.fill(choices, 0);
+ if (empty) {
+ return choices;
+ }
+
for (int type = 0; type < BombType.B_NUM; type++) {
- choices[type] = b_choices[type].getSelectedIndex();
+ choices[type] += b_choices.get(INTNAME)[type].getSelectedIndex() + b_choices.get(EXTNAME)[type].getSelectedIndex();
}
return choices;
}
@Override
public void setEnabled(boolean enabled) {
- for (int type = 0; type < BombType.B_NUM; type++) {
- if ((type == BombType.B_ALAMO)
- && !at2Nukes) {
- b_choices[type].setEnabled(false);
- } else if ((type > BombType.B_TAG)
- && !allowAdvancedAmmo) {
- b_choices[type].setEnabled(false);
- } else if ((type == BombType.B_ASEW)
- || (type == BombType.B_ALAMO)
- || (type == BombType.B_TAG)) {
- b_choices[type].setEnabled(false);
- } else {
- b_choices[type].setEnabled(enabled);
+ for (String title : new String[]{INTNAME, EXTNAME}) {
+ for (int type = 0; type < BombType.B_NUM; type++) {
+ if ((type == BombType.B_ALAMO)
+ && !at2Nukes) {
+ b_choices.get(title)[type].setEnabled(false);
+ } else if ((type > BombType.B_TAG)
+ && !allowAdvancedAmmo) {
+ b_choices.get(title)[type].setEnabled(false);
+ } else if ((type == BombType.B_ASEW)
+ || (type == BombType.B_ALAMO)
+ || (type == BombType.B_TAG)) {
+ b_choices.get(title)[type].setEnabled(false);
+ } else {
+ b_choices.get(title)[type].setEnabled(enabled);
+ }
}
}
}
diff --git a/megamek/src/megamek/client/ui/swing/BombPayloadDialog.java b/megamek/src/megamek/client/ui/swing/BombPayloadDialog.java
index e71703357fd..7ddb34a1b39 100644
--- a/megamek/src/megamek/client/ui/swing/BombPayloadDialog.java
+++ b/megamek/src/megamek/client/ui/swing/BombPayloadDialog.java
@@ -15,24 +15,17 @@
*/
package megamek.client.ui.swing;
-import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
+import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+import java.awt.geom.Dimension2D;
import java.util.StringTokenizer;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JDialog;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
+import javax.swing.*;
import megamek.client.ui.Messages;
import megamek.common.BombType;
@@ -47,6 +40,8 @@ public class BombPayloadDialog extends JDialog implements ActionListener, ItemLi
private boolean confirm = false;
private int limit;
+ private int internalBombLimit=6;
+ private int internalBombCount=0;
private int[] bombs;
private JPanel panButtons = new JPanel();
@@ -86,7 +81,7 @@ public class BombPayloadDialog extends JDialog implements ActionListener, ItemLi
@SuppressWarnings("unchecked")
private void initialize(JFrame parent, String title, int[] b,
boolean spaceBomb, boolean bombDump, int lim, int numFighters) {
- super.setResizable(false);
+ // super.setResizable(false);
this.numFighters = numFighters;
bombs = b;
@@ -183,22 +178,16 @@ public void windowClosing(WindowEvent e) {
pack();
Dimension size = getSize();
- boolean updateSize = false;
- if (size.width < GUIPreferences.getInstance().getMinimumSizeWidth()) {
- size.width = GUIPreferences.getInstance().getMinimumSizeWidth();
- }
- if (size.height < GUIPreferences.getInstance().getMinimumSizeHeight()) {
- size.height = GUIPreferences.getInstance().getMinimumSizeHeight();
- }
- if (updateSize) {
- setSize(size);
- size = getSize();
- }
setLocation((parent.getLocation().x + (parent.getSize().width / 2))
- (size.width / 2), (parent.getLocation().y
+ (parent.getSize().height / 2)) - (size.height / 2));
}
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(500,200);
+ }
+
private void setupButtons() {
butOK.addActionListener(this);
butCancel.addActionListener(this);
diff --git a/megamek/src/megamek/client/ui/swing/ClientGUI.java b/megamek/src/megamek/client/ui/swing/ClientGUI.java
index 91c2ff1f4a3..fa8b123886f 100644
--- a/megamek/src/megamek/client/ui/swing/ClientGUI.java
+++ b/megamek/src/megamek/client/ui/swing/ClientGUI.java
@@ -1880,7 +1880,7 @@ public void loadListFile(Player player) {
* Allow the player to select a MegaMek Unit List file to load. The
* Entity
s in the file will replace any that the player has
* already selected. As such, this method should only be called in the chat
- * lounge. The file can record damage sustained, non- standard munitions
+ * lounge. The file can record damage sustained, non-standard munitions
* selected, and ammunition expended in a prior engagement.
*
* @param player
@@ -1945,7 +1945,9 @@ public String getDescription() {
// the movement turn are considered selectable
entity.setDone(true);
entity.setUnloaded(true);
- if (entity instanceof IBomber) {
+ if (entity instanceof IBomber && (client.getGame().getPhase() != GamePhase.LOUNGE)) {
+ // Only apply bombs when we're going straight into the game; doing this in the lounge
+ // breaks the bombs completely.
((IBomber) entity).applyBombs();
}
}
diff --git a/megamek/src/megamek/client/ui/swing/FiringDisplay.java b/megamek/src/megamek/client/ui/swing/FiringDisplay.java
index 5e9e943fd3e..786d2c10675 100644
--- a/megamek/src/megamek/client/ui/swing/FiringDisplay.java
+++ b/megamek/src/megamek/client/ui/swing/FiringDisplay.java
@@ -188,6 +188,8 @@ public String getHotKeyDesc() {
protected boolean isStrafing = false;
+ protected int phaseInternalBombs = 0;
+
/**
* Keeps track of the Coords that are in a strafing run.
*/
@@ -1203,27 +1205,37 @@ public void ready() {
}
}
- // We need to nag for overheat on capital fighters
- if ((ce() != null) && ce().isCapitalFighter() && GUIP.getNagForOverheat()) {
- int totalheat = 0;
- for (EntityAction action : attacks) {
- if (action instanceof WeaponAttackAction) {
- Mounted weapon = ce().getEquipment(((WeaponAttackAction) action).getWeaponId());
- totalheat += weapon.getCurrentHeat();
+ // Handle some entity bookkeeping
+ if (ce() != null) {
+ // Add internal bombs used this phase to all internal bombs used this round
+ if (ce().isBomber()) {
+ if (phaseInternalBombs > 0) {
+ ((IBomber) ce()).increaseUsedInternalBombs(phaseInternalBombs);
}
- }
- if (totalheat > ce().getHeatCapacity()) {
- // confirm this action
- String title = Messages.getString("FiringDisplay.OverheatNag.title");
- String body = Messages.getString("FiringDisplay.OverheatNag.message");
- ConfirmDialog response = clientgui.doYesNoBotherDialog(title, body);
- if (!response.getShowAgain()) {
- GUIP.setNagForOverheat(false);
+ }
+ // We need to nag for overheat on capital fighters
+ if (ce().isCapitalFighter() && GUIP.getNagForOverheat()) {
+ int totalheat = 0;
+ for (EntityAction action : attacks) {
+ if (action instanceof WeaponAttackAction) {
+ Mounted weapon = ce().getEquipment(((WeaponAttackAction) action).getWeaponId());
+ totalheat += weapon.getCurrentHeat();
+ }
}
- if (!response.getAnswer()) {
- return;
+ if (totalheat > ce().getHeatCapacity()) {
+ // confirm this action
+ String title = Messages.getString("FiringDisplay.OverheatNag.title");
+ String body = Messages.getString("FiringDisplay.OverheatNag.message");
+ ConfirmDialog response = clientgui.doYesNoBotherDialog(title, body);
+ if (!response.getShowAgain()) {
+ GUIP.setNagForOverheat(false);
+ }
+
+ if (!response.getAnswer()) {
+ return;
+ }
}
}
}
@@ -1257,7 +1269,7 @@ public void ready() {
waa2.setAmmoId(waa.getAmmoId());
waa2.setAmmoMunitionType(waa.getAmmoMunitionType());
waa2.setAmmoCarrier(waa.getAmmoCarrier());
- waa2.setBombPayload(waa.getBombPayload());
+ waa2.setBombPayloads(waa.getBombPayloads());
waa2.setStrafing(waa.isStrafing());
waa2.setStrafingFirstShot(waa.isStrafingFirstShot());
newAttacks.addElement(waa2);
@@ -1287,7 +1299,7 @@ public void ready() {
waa2.setAmmoId(waa.getAmmoId());
waa2.setAmmoMunitionType(waa.getAmmoMunitionType());
waa2.setAmmoCarrier(waa.getAmmoCarrier());
- waa2.setBombPayload(waa.getBombPayload());
+ waa2.setBombPayloads(waa.getBombPayloads());
waa2.setStrafing(waa.isStrafing());
waa2.setStrafingFirstShot(waa.isStrafingFirstShot());
newAttacks.addElement(waa2);
@@ -1496,38 +1508,64 @@ private void updateStrafingTargets() {
clientgui.getUnitDisplay().wPan.setToHit(toHitBuff.toString());
}
- private int[] getBombPayload(boolean isSpace, int limit) {
- int[] payload = new int[BombType.B_NUM];
+ private HashMap getBombPayloads(boolean isSpace, int limit) {
+ HashMap payloads = new HashMap();
+ HashMap loadouts = new HashMap();
+ String[] titles = new String[] {"internal", "external"};
+ for (String title: titles) {
+ payloads.put(title, new int[BombType.B_NUM]);
+ }
+
+ // Have to return after map is filled in, not before
if (!ce().isBomber()) {
- return payload;
+ return payloads;
}
- int[] loadout = ce().getBombLoadout();
- // this part is ugly, but we need to find any other bombing attacks by
- // this
- // entity in the attack list and subtract those payloads from the
- // loadout
- for (EntityAction o : attacks) {
- if (o instanceof WeaponAttackAction) {
- WeaponAttackAction waa = (WeaponAttackAction) o;
- if (waa.getEntityId() == ce().getId()) {
- int[] priorLoad = waa.getBombPayload();
- for (int i = 0; i < priorLoad.length; i++) {
- loadout[i] = loadout[i] - priorLoad[i];
+
+ loadouts.put("internal", ce().getInternalBombLoadout());
+ loadouts.put("external", ce().getExternalBombLoadout());
+
+ for (String title: titles){
+ int[] loadout = loadouts.get(title);
+
+ // this part is ugly, but we need to find any other bombing attacks by this
+ // entity in the attack list and subtract those payloads from the relevant loadout
+ for (EntityAction o : attacks) {
+ if (o instanceof WeaponAttackAction) {
+ WeaponAttackAction waa = (WeaponAttackAction) o;
+ if (waa.getEntityId() == ce().getId()) {
+ int[] priorLoad = waa.getBombPayloads().get(title);
+ for (int i = 0; i < priorLoad.length; i++) {
+ loadout[i] = loadout[i] - priorLoad[i];
+ }
}
}
}
- }
- int numFighters = ce().getActiveSubEntities().size();
- BombPayloadDialog bombsDialog = new BombPayloadDialog(
- clientgui.frame,
- Messages.getString("FiringDisplay.BombNumberDialog" + ".title"),
- loadout, isSpace, false, limit, numFighters);
- bombsDialog.setVisible(true);
- if (bombsDialog.getAnswer()) {
- payload = bombsDialog.getChoices();
+ // Don't bother preparing a dialog for bombs that don't exist.
+ if (Arrays.stream(loadout).sum() <= 0){
+ continue;
+ }
+
+ // Internal bay bombing is limited to 6 items per turn, but other limits may also apply
+ if ("internal".equals(title)) {
+ int usedBombs = ((IBomber) ce()).getUsedInternalBombs();
+ limit = (limit <= -1) ? 6 - usedBombs : Math.min(6 - usedBombs, limit);
+ }
+
+ int numFighters = ce().getActiveSubEntities().size();
+ BombPayloadDialog bombsDialog = new BombPayloadDialog(
+ clientgui.frame,
+ Messages.getString("FiringDisplay.BombNumberDialog" + ".title") + ", " + title,
+ loadout, isSpace, false, limit, numFighters);
+ bombsDialog.setVisible(true);
+ if (bombsDialog.getAnswer()) {
+ int[] choices = bombsDialog.getChoices();
+ for (int i = 0; i < choices.length; i++) {
+ payloads.get(title)[i] += choices[i];
+ }
+ }
}
- return payload;
+ return payloads;
}
/**
@@ -1621,15 +1659,11 @@ void fire() {
// check for a bomb payload dialog
if (mounted.getType().hasFlag(WeaponType.F_SPACE_BOMB)) {
- int[] payload = getBombPayload(true, -1);
- waa.setBombPayload(payload);
+ waa.setBombPayloads(getBombPayloads(true, -1));
} else if (mounted.getType().hasFlag(WeaponType.F_DIVE_BOMB)) {
- int[] payload = getBombPayload(false, -1);
- waa.setBombPayload(payload);
+ waa.setBombPayloads(getBombPayloads(false, -1));
} else if (mounted.getType().hasFlag(WeaponType.F_ALT_BOMB)) {
- // if the user cancels, then return
- int[] payload = getBombPayload(false, 2);
- waa.setBombPayload(payload);
+ waa.setBombPayloads(getBombPayloads(false, 2));
}
if ((mounted.getLinked() != null)
@@ -1664,6 +1698,9 @@ void fire() {
waa.setStrafingFirstShot(firstShot);
firstShot = false;
+ // Handle incrementing internal-bay weapons that are not used in bomb bay attacks
+ incrementInternalBombs(waa);
+
// Temporarily add attack into the game. On turn done
// this will be recomputed from the local
// @attacks EntityAttackLog, but Game actions
@@ -1807,6 +1844,11 @@ protected void clearAttacks() {
// restore any other movement to default
ce().setSecondaryFacing(ce().getFacing());
ce().setArmsFlipped(false);
+
+ // restore count of internal bombs dropped this phase.
+ if(ce().isBomber()) {
+ phaseInternalBombs = ((IBomber)ce()).getUsedInternalBombs();
+ }
}
/**
@@ -1827,6 +1869,7 @@ protected void removeLastFiring() {
if (o instanceof WeaponAttackAction) {
WeaponAttackAction waa = (WeaponAttackAction) o;
ce().getEquipment(waa.getWeaponId()).setUsedThisRound(false);
+ decrementInternalBombs(waa);
removeAttack(o);
clientgui.getUnitDisplay().wPan.displayMech(ce());
clientgui.getClient().getGame().removeAction(o);
@@ -1966,6 +2009,9 @@ public void updateTarget() {
} else if (m.isInBearingsOnlyMode()) {
clientgui.getUnitDisplay().wPan.setToHit(Messages.getString("FiringDisplay.bearingsOnlyWrongPhase"));
setFireEnabled(false);
+ } else if (m.isInternalBomb() && phaseInternalBombs >= 6) {
+ clientgui.getUnitDisplay().wPan.setToHit(Messages.getString("WeaponAttackAction.AlreadyUsedMaxInternalBombs"));
+ setFireEnabled(false);
} else if (toHit.getValue() == TargetRoll.IMPOSSIBLE) {
clientgui.getUnitDisplay().wPan.setToHit(toHit);
setFireEnabled(false);
@@ -2674,4 +2720,23 @@ private boolean validStrafingCoord(Coords newCoord) {
}
return isConsecutive && isInaLine;
}
+
+ private void incrementInternalBombs(WeaponAttackAction waa) {
+ updateInternalBombs(waa, 1);
+ }
+ private void decrementInternalBombs(WeaponAttackAction waa) {
+ updateInternalBombs(waa, -1);
+ }
+ private void updateInternalBombs(WeaponAttackAction waa, int amt) {
+ if (ce().isBomber()) {
+ if (ce().getEquipment(waa.getWeaponId()).isInternalBomb()) {
+ int usedInternalBombs = ((IBomber) ce()).getUsedInternalBombs();
+ phaseInternalBombs += amt;
+ if (phaseInternalBombs < usedInternalBombs) {
+ phaseInternalBombs = usedInternalBombs;
+ }
+ }
+ }
+
+ }
}
diff --git a/megamek/src/megamek/client/ui/swing/ForceGenerationOptionsPanel.java b/megamek/src/megamek/client/ui/swing/ForceGenerationOptionsPanel.java
index e0cfdf888e0..8210082d979 100644
--- a/megamek/src/megamek/client/ui/swing/ForceGenerationOptionsPanel.java
+++ b/megamek/src/megamek/client/ui/swing/ForceGenerationOptionsPanel.java
@@ -81,7 +81,7 @@ public enum Use {
private static final int[] UNIT_TYPES = {
UnitType.MEK, UnitType.TANK, UnitType.BATTLE_ARMOR, UnitType.INFANTRY, UnitType.PROTOMEK,
- UnitType.VTOL, UnitType.NAVAL, UnitType.CONV_FIGHTER, UnitType.AERO, UnitType.SMALL_CRAFT,
+ UnitType.VTOL, UnitType.NAVAL, UnitType.CONV_FIGHTER, UnitType.AEROSPACEFIGHTER, UnitType.AERO, UnitType.SMALL_CRAFT,
UnitType.DROPSHIP, UnitType.JUMPSHIP, UnitType.WARSHIP, UnitType.SPACE_STATION
};
private static final int EARLIEST_YEAR = 2398;
@@ -91,7 +91,7 @@ public enum Use {
//region Constructors
public ForceGenerationOptionsPanel(Use use) {
setLayout(new GridBagLayout());
-
+
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
@@ -445,7 +445,7 @@ public void focusLost(FocusEvent e) {
RATGenerator.getInstance().loadYear(ratGenYear);
}
}
-
+
public void updateGeneratedUnits(List list) {
panUnitTypeOptions.updateGeneratedUnits(list);
}
@@ -464,7 +464,7 @@ public Component getListCellRendererComponent(JList> list, Object value, int i
return this;
}
};
-
+
private Comparator factionSorter = new Comparator<>() {
@Override
public int compare(FactionRecord o1, FactionRecord o2) {
@@ -479,31 +479,31 @@ abstract static class UnitTypeOptions extends JPanel {
private static final long serialVersionUID = -7141802206126462796L;
abstract public void optionsChanged();
-
+
public Integer getIntegerVal(String key) {
return null;
}
-
+
public Boolean getBooleanVal(String key) {
return null;
}
-
+
public String getStringVal(String key) {
return null;
}
-
+
public List> getListVal(String key) {
return new ArrayList<>();
}
-
+
public abstract void updateGeneratedUnits(List list);
}
-
+
public class RATGenUnitTypeOptions extends UnitTypeOptions {
private static final long serialVersionUID = 6536972747395725718L;
private Map cardMap = new HashMap<>();
-
+
public RATGenUnitTypeOptions() {
setLayout(new CardLayout());
for (int i = 0; i < cbUnitType.getItemCount(); i++) {
@@ -513,17 +513,17 @@ public RATGenUnitTypeOptions() {
add(card, cbUnitType.getItemAt(i));
}
}
-
+
@Override
public void optionsChanged() {
((CardLayout) getLayout()).show(this, (String) cbUnitType.getSelectedItem());
}
-
+
private RATGenUnitTypeCard currentCard() {
String selectedCard = (String) cbUnitType.getSelectedItem();
return cardMap.get(selectedCard);
}
-
+
@Override
public Integer getIntegerVal(String key) {
switch (key) {
@@ -535,7 +535,7 @@ public Integer getIntegerVal(String key) {
return null;
}
}
-
+
@Override
public List> getListVal(String key) {
switch (key) {
@@ -568,7 +568,7 @@ private static class RATGenUnitTypeCard extends JPanel {
private List roleChecks = new ArrayList<>();
private ButtonGroup networkButtons = new ButtonGroup();
private List subtypeChecks = new ArrayList<>();
-
+
public RATGenUnitTypeCard(int unitType) {
setLayout(new BorderLayout());
@@ -576,11 +576,11 @@ public RATGenUnitTypeCard(int unitType) {
panWeightClass.setBorder(BorderFactory.createTitledBorder(Messages
.getString("RandomArmyDialog.WeightClass")));
add(panWeightClass, BorderLayout.WEST);
-
+
JPanel panRoles = new JPanel(new GridBagLayout());
panRoles.setBorder(BorderFactory.createTitledBorder(Messages
.getString("RandomArmyDialog.MissionRole")));
-
+
JPanel panStrictness = new JPanel();
panStrictness.add(new JLabel(Messages.getString("RandomArmyDialog.Strictness")));
cbRoleStrictness.setToolTipText(Messages.getString("RandomArmyDialog.Strictness.tooltip"));
@@ -589,7 +589,7 @@ public RATGenUnitTypeCard(int unitType) {
cbRoleStrictness.addItem(Messages.getString("RandomArmyDialog.High"));
cbRoleStrictness.setSelectedIndex(1);
panStrictness.add(cbRoleStrictness);
-
+
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
@@ -599,17 +599,17 @@ public RATGenUnitTypeCard(int unitType) {
c.weightx = 0.0;
c.weighty = 0.0;
panRoles.add(panStrictness, c);
-
+
add(panRoles, BorderLayout.CENTER);
JPanel panNetwork = new JPanel(new GridBagLayout());
panNetwork.setBorder(BorderFactory.createTitledBorder(Messages
.getString("RandomArmyDialog.Network")));
add(panNetwork, BorderLayout.EAST);
-
+
JPanel panMotive = new JPanel();
add(panMotive, BorderLayout.NORTH);
-
+
switch (unitType) {
case UnitType.MEK:
addWeightClasses(panWeightClass, EntityWeightClass.WEIGHT_ULTRA_LIGHT,
@@ -631,6 +631,7 @@ public RATGenUnitTypeCard(int unitType) {
addWeightClasses(panWeightClass, EntityWeightClass.WEIGHT_ULTRA_LIGHT,
EntityWeightClass.WEIGHT_ASSAULT, true);
break;
+ case UnitType.AEROSPACEFIGHTER:
case UnitType.AERO:
addWeightClasses(panWeightClass, EntityWeightClass.WEIGHT_LIGHT,
EntityWeightClass.WEIGHT_HEAVY, false);
@@ -646,7 +647,7 @@ public RATGenUnitTypeCard(int unitType) {
default:
panWeightClass.setVisible(false);
}
-
+
for (MissionRole role : MissionRole.values()) {
if (role.fitsUnitType(unitType)) {
JCheckBox chk = new JCheckBox(Messages.getString("MissionRole." + role));
@@ -674,7 +675,7 @@ public RATGenUnitTypeCard(int unitType) {
}
panRoles.add(roleChecks.get(i), c);
}
-
+
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
@@ -690,6 +691,7 @@ public RATGenUnitTypeCard(int unitType) {
case UnitType.VTOL:
case UnitType.NAVAL:
case UnitType.CONV_FIGHTER:
+ case UnitType.AEROSPACEFIGHTER:
case UnitType.AERO:
addNetworkButton(panNetwork, c, networkButtons, Messages.getString("RandomArmyDialog.NoNetwork"),
ModelRecord.NETWORK_NONE);
@@ -733,7 +735,7 @@ public RATGenUnitTypeCard(int unitType) {
ModelRecord.NETWORK_NAVAL_C3);
break;
}
-
+
switch (unitType) {
case UnitType.TANK:
panMotive.add(createSubtypeCheck("hover", true));
@@ -782,7 +784,7 @@ private void addWeightClasses(JPanel panel, int start, int end, boolean all) {
c.weightx = 0.0;
c.weighty = 0.0;
panel.add(cbWeightClass);
-
+
c.gridx = 0;
c.gridwidth = 2;
for (int i = start; i <= end; i++) {
@@ -869,22 +871,22 @@ public List getMotiveTypes() {
.map(chk -> EntityMovementMode.parseFromString(chk.getName())).collect(Collectors.toList());
}
}
-
+
private class FormationUnitTypeOptions extends UnitTypeOptions {
private static final long serialVersionUID = -6448946137013919069L;
FormationTypesCard groundCard;
FormationTypesCard airCard;
-
+
public FormationUnitTypeOptions() {
setLayout(new CardLayout());
-
+
groundCard = new FormationTypesCard(true);
airCard = new FormationTypesCard(false);
add(groundCard, "Ground");
add(airCard, "Air");
}
-
+
@Override
public void optionsChanged() {
if (getUnitType() != null) {
@@ -893,7 +895,7 @@ public void optionsChanged() {
}
currentCard().updateUnitType(getUnitType());
}
-
+
private FormationTypesCard currentCard() {
if ((getUnitType() != null) && (getUnitType() >= UnitType.CONV_FIGHTER)) {
return airCard;
@@ -901,7 +903,7 @@ private FormationTypesCard currentCard() {
return groundCard;
}
}
-
+
@Override
public Integer getIntegerVal(String key) {
switch (key) {
@@ -915,7 +917,7 @@ public Integer getIntegerVal(String key) {
return null;
}
}
-
+
@Override
public Boolean getBooleanVal(String key) {
switch (key) {
@@ -927,7 +929,7 @@ public Boolean getBooleanVal(String key) {
return null;
}
}
-
+
@Override
public String getStringVal(String key) {
if ("formationType".equals(key)) {
@@ -936,7 +938,7 @@ public String getStringVal(String key) {
return null;
}
}
-
+
@Override
public void updateGeneratedUnits(List list) {
currentCard().setGeneratedUnits(list);
@@ -958,13 +960,13 @@ private class FormationTypesCard extends JPanel {
private Map networkOptions = new LinkedHashMap<>();
private JTextArea txtNoFormation = new JTextArea();
private List generatedUnits = null;
-
+
public FormationTypesCard(boolean groundUnit) {
setLayout(new GridBagLayout());
-
+
JPanel panFormations = new JPanel(new GridBagLayout());
JPanel panOtherOptions = new JPanel(new GridBagLayout());
-
+
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
@@ -972,14 +974,14 @@ public FormationTypesCard(boolean groundUnit) {
c.weightx = 0.5;
c.weighty = 1.0;
add(panFormations, c);
-
+
c.gridx = 1;
c.gridy = 0;
c.anchor = GridBagConstraints.NORTHWEST;
c.weightx = 0.5;
c.weighty = 0.0;
add(panOtherOptions, c);
-
+
// Sort main types alphabetically, and subtypes alphabetically within the main.
List formations = FormationType.getAllFormations().stream()
.filter(ft -> ft.isGround() == groundUnit).collect(Collectors.toList());
@@ -987,7 +989,7 @@ public FormationTypesCard(boolean groundUnit) {
.collect(Collectors.groupingBy(FormationType::getCategory, TreeMap::new,
Collectors.mapping(FormationType::getName,
Collectors.toCollection(TreeSet::new))));
-
+
int rows = (formations.size() + 1) / 2;
c = new GridBagConstraints();
@@ -998,7 +1000,7 @@ public FormationTypesCard(boolean groundUnit) {
c.fill = GridBagConstraints.NONE;
c.weightx = 0.0;
c.weighty = 1.0;
-
+
Insets mainInsets = new Insets(0, 10, 0, 10);
Insets subInsets = new Insets(0, 30, 0, 10);
for (String group : formationGroups.keySet()) {
@@ -1034,8 +1036,8 @@ public FormationTypesCard(boolean groundUnit) {
c.gridy = 0;
}
}
-
- ButtonGroup btnGroup = new ButtonGroup();
+
+ ButtonGroup btnGroup = new ButtonGroup();
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.NORTHWEST;
@@ -1046,7 +1048,7 @@ public FormationTypesCard(boolean groundUnit) {
panOtherOptions.add(bSimpleFormation, c);
bSimpleFormation.addItemListener(ev -> tNumUnits.setEnabled(!bSimpleFormation.isSelected()));
btnGroup.add(bSimpleFormation);
-
+
c.gridx = 0;
c.gridy++;
c.anchor = GridBagConstraints.NORTHWEST;
@@ -1154,7 +1156,7 @@ public int numOtherUnits() {
return 0;
}
}
-
+
public int getOtherUnitType() {
String otherUnitType = (String) cbOtherUnitType.getSelectedItem();
if (!bOtherUnitType.isSelected() || (otherUnitType == null)) {
@@ -1162,7 +1164,7 @@ public int getOtherUnitType() {
}
return ModelRecord.parseUnitType(otherUnitType);
}
-
+
public void updateUnitType(int ut) {
boolean selectionDisabled = false;
for (Enumeration e = formationBtnGroup.getElements(); e.hasMoreElements();) {
@@ -1186,13 +1188,13 @@ public void updateUnitType(int ut) {
//We shouldn't reach this point, but if we do the previous selection doesn't change.
}
}
-
+
public int getNetwork() {
String networkOption = (String) cbNetwork.getSelectedItem();
return (networkOptions.get(networkOption) != null) ? networkOptions.get((networkOption))
: ModelRecord.NETWORK_NONE;
}
-
+
private void showAnalysis() {
List params = new ArrayList<>();
FormationType ft = FormationType.getFormationType(getFormation());
@@ -1217,7 +1219,7 @@ private void showAnalysis() {
params, numUnits, getNetwork());
afd.setVisible(true);
}
-
+
public void setGeneratedUnits(List list) {
generatedUnits = list;
txtNoFormation.setVisible(list == null || list.isEmpty());
diff --git a/megamek/src/megamek/client/ui/swing/MovementDisplay.java b/megamek/src/megamek/client/ui/swing/MovementDisplay.java
index f74ca9d3e16..2e2414f49e1 100644
--- a/megamek/src/megamek/client/ui/swing/MovementDisplay.java
+++ b/megamek/src/megamek/client/ui/swing/MovementDisplay.java
@@ -196,6 +196,7 @@ public enum MoveCommand implements PhaseCommand {
* Priority that determines this buttons order
*/
public int priority;
+
MoveCommand(String c, int f) {
cmd = c;
flag = f;
@@ -225,7 +226,7 @@ public String toString() {
public String getHotKeyDesc() {
String result = "";
- String msg_next= Messages.getString("Next");
+ String msg_next = Messages.getString("Next");
String msg_previous = Messages.getString("Previous");
String msg_left = Messages.getString("Left");
String msg_right = Messages.getString("Right");
@@ -598,7 +599,7 @@ public void performAction() {
}
computeMovementEnvelope(ce);
}
- });
+ });
// Register the action for mode conversion
controller.registerCommandAction(KeyCommandBind.TOGGLE_CONVERSIONMODE.cmd,
@@ -794,31 +795,33 @@ private boolean isEnabled(MoveCommand c) {
/**
* Signals Unit Display to update later on the AWT event stack.
- * See Issue:#4876 and #4444. This is done to prevent blank general tab when switching
+ * See Issue:#4876 and #4444. This is done to prevent blank general tab when switching
* units when the map is zoomed all the way out.
*/
private void updateUnitDisplayLater(Entity ce) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- clientgui.getUnitDisplay().displayEntity(ce);
- clientgui.getUnitDisplay().showPanel("movement");
+ clientgui.getUnitDisplay().displayEntity(ce);
+ clientgui.getUnitDisplay().showPanel("movement");
}
});
}
/**
- * Sets buttons to their proper state, but lets Swing do this later after all the
+ * Sets buttons to their proper state, but lets Swing do this later after all the
* current BoardView repaints and updates are complete. This is done to prevent some
* buttons from painting correctly when the maps is zoomed way out. See Issue: #4444
*/
private void updateButtonsLater() {
SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- updateButtons();
- };
+ @Override
+ public void run() {
+ updateButtons();
+ }
+
+ ;
});
}
@@ -904,7 +907,7 @@ private void updateButtons() {
// Infantry and Tank - Fortify
if (isInfantry
- && ce.hasWorkingMisc(MiscType.F_TRENCH_CAPABLE)) {
+ && ce.hasWorkingMisc(MiscType.F_TRENCH_CAPABLE)) {
// Crews adrift in space or atmosphere can't do this
if (ce instanceof EjectedCrew && (ce.isSpaceborne() || ce.isAirborne())) {
getBtn(MoveCommand.MOVE_DIG_IN).setEnabled(false);
@@ -949,7 +952,7 @@ private void updateButtons() {
getBtn(MoveCommand.MOVE_SHAKE_OFF).setEnabled(
(ce instanceof Tank)
- && (ce.getSwarmAttackerId() != Entity.NONE));
+ && (ce.getSwarmAttackerId() != Entity.NONE));
setFleeEnabled(ce.canFlee());
if (gOpts.booleanOption(OptionsConstants.ADVGRNDMOV_VEHICLES_CAN_EJECT) && (ce instanceof Tank)) {
@@ -997,7 +1000,7 @@ private void addStepToMovePath(MoveStepType moveStep) {
updateMove();
}
- private void addStepsToMovePath(MoveStepType ... moveSteps ) {
+ private void addStepsToMovePath(MoveStepType... moveSteps) {
for (MoveStepType moveStep : moveSteps) {
cmd.addStep(moveStep);
}
@@ -1009,7 +1012,7 @@ private void addStepToMovePath(MoveStepType moveStep, Entity entity) {
updateMove();
}
- private void addStepToMovePath(MoveStepType moveStep, TreeMap> targets) {
+ private void addStepToMovePath(MoveStepType moveStep, TreeMap> targets) {
cmd.addStep(moveStep, targets);
updateMove();
}
@@ -1019,12 +1022,12 @@ private void addStepToMovePath(MoveStepType moveStep, boolean noCost) {
updateMove();
}
- private void addStepToMovePath(MoveStepType moveStep, boolean noCost, boolean isManeuver, int maneuverType) {
+ private void addStepToMovePath(MoveStepType moveStep, boolean noCost, boolean isManeuver, int maneuverType) {
cmd.addStep(moveStep, noCost, isManeuver, maneuverType);
updateMove();
}
- private void addStepsToMovePath(boolean noCost, boolean isManeuver, int maneuverType, MoveStepType ... moveSteps) {
+ private void addStepsToMovePath(boolean noCost, boolean isManeuver, int maneuverType, MoveStepType... moveSteps) {
for (MoveStepType moveStep : moveSteps) {
cmd.addStep(moveStep, noCost, isManeuver, maneuverType);
}
@@ -1046,7 +1049,7 @@ private void addStepToMovePath(MoveStepType moveStep, int additionalIntData) {
updateMove();
}
- private void addStepToMovePath(MoveStepType moveStep, int recover ,int mineToLay) {
+ private void addStepToMovePath(MoveStepType moveStep, int recover, int mineToLay) {
cmd.addStep(moveStep, recover, mineToLay);
updateMove();
}
@@ -1105,7 +1108,7 @@ protected void updateDonePanel() {
}
}
- private List computeTurnDetails(){
+ private List computeTurnDetails() {
String validTextColor = AbstractBoardViewOverlay.colorToHex(AbstractBoardViewOverlay.getTextColor());
String invalidTextColor = AbstractBoardViewOverlay.colorToHex(AbstractBoardViewOverlay.getTextColor(), 0.7f);
@@ -1116,7 +1119,7 @@ private List computeTurnDetails(){
boolean accumLegal = true;
String unicodeIcon = "";
ArrayList turnDetails = new ArrayList<>();
- for( final Enumeration step = cmd.getSteps(); step.hasMoreElements();) {
+ for (final Enumeration step = cmd.getSteps(); step.hasMoreElements(); ) {
MoveStep currentStep = step.nextElement();
MoveStepType currentType = currentStep.getType();
int currentDanger = currentStep.isDanger() ? 1 : 0;
@@ -1442,7 +1445,7 @@ public synchronized void ready() {
return;
}
- if ((ce().canUnjamRAC()) && (GUIP.getNagForNoUnJamRAC()) && (!isUnJammingRAC)){
+ if ((ce().canUnjamRAC()) && (GUIP.getNagForNoUnJamRAC()) && (!isUnJammingRAC)) {
// confirm this action
String title = Messages.getString("MovementDisplay.ConfirmUnJamRACDlg.title");
String body = Messages.getString("MovementDisplay.ConfirmUnJamRACDlg.message");
@@ -1457,7 +1460,7 @@ public synchronized void ready() {
}
cmd.clipToPossible();
- if ( (cmd.length() == 0) && (!ce().isAirborne()) && needNagForNoAction()) {
+ if ((cmd.length() == 0) && (!ce().isAirborne()) && needNagForNoAction()) {
// Hmm... no movement steps, confirm this action
String title = Messages.getString("MovementDisplay.ConfirmNoMoveDlg.title");
String body = Messages.getString("MovementDisplay.ConfirmNoMoveDlg.message");
@@ -1508,9 +1511,9 @@ public synchronized void ready() {
&& GUIP.getNagForSprint()
// no need to nag for vehicles using overdrive if they already get a PSR nag
&& !((cmd.getEntity() instanceof Tank
- || (cmd.getEntity() instanceof QuadVee
- && cmd.getEntity().getConversionMode() == QuadVee.CONV_MODE_VEHICLE)
- && GUIP.getNagForPSR()))) {
+ || (cmd.getEntity() instanceof QuadVee
+ && cmd.getEntity().getConversionMode() == QuadVee.CONV_MODE_VEHICLE)
+ && GUIP.getNagForPSR()))) {
ConfirmDialog nag = new ConfirmDialog(clientgui.frame,
Messages.getString("MovementDisplay.areYouSure"),
Messages.getString("MovementDisplay.ConfirmSprint"), true);
@@ -1640,7 +1643,7 @@ public synchronized void ready() {
boolean flyoff = false;
if ((null != cmd)
&& (cmd.contains(MoveStepType.OFF) || cmd
- .contains(MoveStepType.RETURN))) {
+ .contains(MoveStepType.RETURN))) {
flyoff = true;
}
boolean landing = false;
@@ -1703,9 +1706,9 @@ public synchronized void ready() {
&& !cmd.contains(MoveStepType.FORWARDS) && !cmd.contains(MoveStepType.FLEE)
&& cmd.getFinalElevation() > 0
&& ce().getGame().getBoard().getHex(cmd.getFinalCoords())
- .terrainLevel(Terrains.BLDG_ELEV) < cmd.getFinalElevation()
+ .terrainLevel(Terrains.BLDG_ELEV) < cmd.getFinalElevation()
&& ce().getGame().getBoard().getHex(cmd.getFinalCoords())
- .terrainLevel(Terrains.BRIDGE_ELEV) < cmd.getFinalElevation()) {
+ .terrainLevel(Terrains.BRIDGE_ELEV) < cmd.getFinalElevation()) {
String title = Messages.getString("MovementDisplay.MicroliteMove.title");
String body = Messages.getString("MovementDisplay.MicroliteMove.message");
clientgui.doAlertDialog(title, body);
@@ -1796,7 +1799,7 @@ private void currentMove(Coords dest) {
if (shiftheld || (gear == GEAR_TURN)) {
cmd.rotatePathfinder(cmd.getFinalCoords().direction(dest), false, ManeuverType.MAN_NONE);
} else if ((gear == GEAR_JUMP)
- && (ce().getJumpType() == Mech.JUMP_BOOSTER)) {
+ && (ce().getJumpType() == Mech.JUMP_BOOSTER)) {
// Jumps with mechanical jump boosters are special
Coords src;
if (cmd.getLastStep() != null) {
@@ -1866,7 +1869,7 @@ private void currentMove(Coords dest) {
cmd.findPathTo(dest, MoveStepType.CHARGE);
// The path planner shouldn't actually add the charge step
if (cmd.getFinalCoords().equals(dest)
- && (cmd.getLastStep().getType() != MoveStepType.CHARGE)) {
+ && (cmd.getLastStep().getType() != MoveStepType.CHARGE)) {
cmd.removeLastStep();
addStepToMovePath(MoveStepType.CHARGE);
}
@@ -1874,7 +1877,7 @@ private void currentMove(Coords dest) {
cmd.findPathTo(dest, MoveStepType.DFA);
// The path planner shouldn't actually add the DFA step
if (cmd.getFinalCoords().equals(dest)
- && (cmd.getLastStep().getType() != MoveStepType.DFA)) {
+ && (cmd.getLastStep().getType() != MoveStepType.DFA)) {
cmd.removeLastStep();
addStepToMovePath(MoveStepType.DFA);
}
@@ -2085,9 +2088,9 @@ public synchronized void hexMoused(BoardViewEvent b) {
toDefender = AirmechRamAttackAction.getDamageFor(ce, cmd.getHexesMoved());
} else {
toDefender = ChargeAttackAction.getDamageFor(
- ce, clientgui.getClient().getGame().getOptions()
- .booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_CHARGE_DAMAGE),
- cmd.getHexesMoved());
+ ce, clientgui.getClient().getGame().getOptions()
+ .booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_CHARGE_DAMAGE),
+ cmd.getHexesMoved());
if (target.getTargetType() == Targetable.TYPE_ENTITY) {
Entity te = (Entity) target;
toAttacker = ChargeAttackAction.getDamageTakenBy(ce, te,
@@ -2095,7 +2098,7 @@ public synchronized void hexMoused(BoardViewEvent b) {
.booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_CHARGE_DAMAGE),
cmd.getHexesMoved());
} else if ((target.getTargetType() == Targetable.TYPE_FUEL_TANK)
- || (target.getTargetType() == Targetable.TYPE_BUILDING)) {
+ || (target.getTargetType() == Targetable.TYPE_BUILDING)) {
Building bldg = clientgui.getClient().getGame().getBoard().getBuildingAt(moveto);
toAttacker = ChargeAttackAction.getDamageTakenBy(ce, bldg, moveto);
}
@@ -2226,8 +2229,7 @@ private void updateTakeCoverButton() {
private synchronized void updateChaffButton() {
Entity ce = ce();
- if (ce == null )
- {
+ if (ce == null) {
return;
}
@@ -2256,7 +2258,7 @@ private synchronized void updateProneButtons() {
} else if (cmd.getFinalHullDown()) {
if (isMech) {
setGetUpEnabled(!ce.isImmobile() && !ce.isStuck()
- && !((Mech) ce).cannotStandUpFromHullDown());
+ && !((Mech) ce).cannotStandUpFromHullDown());
} else {
setGetUpEnabled(!ce.isImmobile() && !ce.isStuck());
}
@@ -2265,7 +2267,7 @@ private synchronized void updateProneButtons() {
} else {
setGetUpEnabled(false);
setGoProneEnabled(!ce.isImmobile() && isMech && !ce.isStuck()
- && !(getBtn(MoveCommand.MOVE_GET_UP).isEnabled()));
+ && !(getBtn(MoveCommand.MOVE_GET_UP).isEnabled()));
if (!(ce instanceof Tank) && !(ce instanceof QuadVee
&& ce.getConversionMode() == QuadVee.CONV_MODE_VEHICLE)) {
setHullDownEnabled(ce.canGoHullDown());
@@ -2274,11 +2276,11 @@ private synchronized void updateProneButtons() {
// check if it's moved into a fortified position
if (cmd.getLastStep() != null) {
boolean hullDownEnabled = clientgui.getClient()
- .getGame().getOptions()
- .booleanOption(OptionsConstants.ADVGRNDMOV_TACOPS_HULL_DOWN);
+ .getGame().getOptions()
+ .booleanOption(OptionsConstants.ADVGRNDMOV_TACOPS_HULL_DOWN);
Hex occupiedHex = clientgui.getClient().getGame()
- .getBoard()
- .getHex(cmd.getLastStep().getPosition());
+ .getBoard()
+ .getHex(cmd.getLastStep().getPosition());
boolean fortifiedHex = occupiedHex
.containsTerrain(Terrains.FORTIFIED);
setHullDownEnabled(hullDownEnabled && fortifiedHex);
@@ -2301,14 +2303,14 @@ private void updateRACButton() {
GameOptions opts = clientgui.getClient().getGame().getOptions();
setUnjamEnabled(ce.canUnjamRAC()
&& ((gear == MovementDisplay.GEAR_LAND)
- || (gear == MovementDisplay.GEAR_TURN)
- || (gear == MovementDisplay.GEAR_BACKUP))
+ || (gear == MovementDisplay.GEAR_TURN)
+ || (gear == MovementDisplay.GEAR_BACKUP))
&& ((cmd.getMpUsed() <= ce.getWalkMP())
- || (cmd.getLastStep().isOnlyPavement()
- && (cmd.getMpUsed() <= (ce.getWalkMP() + 1))))
+ || (cmd.getLastStep().isOnlyPavement()
+ && (cmd.getMpUsed() <= (ce.getWalkMP() + 1))))
&& !(opts.booleanOption(OptionsConstants.ADVANCED_TACOPS_TANK_CREWS)
- && (cmd.getMpUsed() > 0) && (ce instanceof Tank)
- && (ce.getCrew().getSize() < 2)));
+ && (cmd.getMpUsed() > 0) && (ce instanceof Tank)
+ && (ce.getCrew().getSize() < 2)));
}
private void updateSearchlightButton() {
@@ -2589,9 +2591,9 @@ private void updateFlyOffButton() {
if (a.isSpheroid() && !board.inSpace()) {
setFlyOffEnabled((position != null) && (ce.getWalkMP() > 0)
&& ((position.getX() == 0)
- || (position.getX() == (board.getWidth() - 1))
- || (position.getY() == 0)
- || (position.getY() == (board.getHeight() - 1))));
+ || (position.getX() == (board.getWidth() - 1))
+ || (position.getY() == 0)
+ || (position.getY() == (board.getHeight() - 1))));
return;
}
@@ -2603,13 +2605,13 @@ private void updateFlyOffButton() {
boolean evenx = (position.getX() % 2) == 0;
if ((velocityLeft > 0) && (((position.getX() == 0) && ((facing == 5) || (facing == 4)))
|| ((position.getX() == (board.getWidth() - 1))
- && ((facing == 1) || (facing == 2)))
+ && ((facing == 1) || (facing == 2)))
|| ((position.getY() == 0) && ((facing == 1) || (facing == 5) || (facing == 0)) && evenx)
|| ((position.getY() == 0) && (facing == 0))
|| ((position.getY() == (board.getHeight() - 1))
- && ((facing == 2) || (facing == 3) || (facing == 4)) && !evenx)
+ && ((facing == 2) || (facing == 3) || (facing == 4)) && !evenx)
|| ((position.getY() == (board.getHeight() - 1))
- && (facing == 3)))) {
+ && (facing == 3)))) {
setFlyOffEnabled(true);
} else {
setFlyOffEnabled(false);
@@ -2665,7 +2667,7 @@ private void updateBootleggerButton() {
}
if (!clientgui.getClient().getGame().getOptions()
- .booleanOption(OptionsConstants.ADVGRNDMOV_VEHICLE_ADVANCED_MANEUVERS)) {
+ .booleanOption(OptionsConstants.ADVGRNDMOV_VEHICLE_ADVANCED_MANEUVERS)) {
return;
}
@@ -2709,7 +2711,7 @@ private void updateStartupButton() {
}
if (!clientgui.getClient().getGame().getOptions()
- .booleanOption(OptionsConstants.RPG_MANUAL_SHUTDOWN)) {
+ .booleanOption(OptionsConstants.RPG_MANUAL_SHUTDOWN)) {
return;
}
@@ -2728,7 +2730,7 @@ private void updateSelfDestructButton() {
}
if (!clientgui.getClient().getGame().getOptions()
- .booleanOption(OptionsConstants.ADVANCED_TACOPS_SELF_DESTRUCT)) {
+ .booleanOption(OptionsConstants.ADVANCED_TACOPS_SELF_DESTRUCT)) {
return;
}
@@ -2897,8 +2899,8 @@ private void updateBombButton() {
if (ce().isBomber()
&& ((ce() instanceof LandAirMech)
- || clientgui.getClient().getGame().getOptions()
- .booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_VTOL_ATTACKS))
+ || clientgui.getClient().getGame().getOptions()
+ .booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_VTOL_ATTACKS))
&& ((IBomber) ce()).getBombPoints() > 0) {
setBombEnabled(true);
}
@@ -3018,8 +3020,8 @@ private void updateLayMineButton() {
setLayMineEnabled(false);
} else if (ce instanceof BattleArmor) {
setLayMineEnabled(cmd.getLastStep() == null
- || cmd.isJumping()
- || cmd.getLastStepMovementType().equals(EntityMovementType.MOVE_VTOL_WALK));
+ || cmd.isJumping()
+ || cmd.getLastStepMovementType().equals(EntityMovementType.MOVE_VTOL_WALK));
} else {
setLayMineEnabled(true);
}
@@ -3068,7 +3070,7 @@ private Entity getMountedUnit() {
int i = 0;
for (Integer bn : bayChoices) {
retVal[i++] = bn.toString() + " (Free Slots: "
- + (int) choice.getBayById(bn).getUnused() + ")";
+ + (int) choice.getBayById(bn).getUnused() + ")";
}
if (bayChoices.size() > 1) {
String bayString = (String) JOptionPane
@@ -3081,7 +3083,7 @@ private Entity getMountedUnit() {
JOptionPane.QUESTION_MESSAGE, null, retVal,
null);
ce.setTargetBay(Integer.parseInt(bayString.substring(0,
- bayString.indexOf(" "))));
+ bayString.indexOf(" "))));
// We need to update the entity here so that the server knows
// about our target bay
clientgui.getClient().sendUpdateEntity(ce);
@@ -3103,7 +3105,7 @@ private Entity getMountedUnit() {
Vector choices = new Vector<>();
for (Entity other : game.getEntitiesVector(cmd.getFinalCoords())) {
if (other.isLoadableThisTurn() && (ce() != null)
- && ce().canLoad(other, false)) {
+ && ce().canLoad(other, false)) {
choices.addElement(other);
}
}
@@ -3118,12 +3120,12 @@ && ce().canLoad(other, false)) {
if (choices.size() > 1) {
String input = (String) JOptionPane
.showInputDialog(clientgui,
- Messages.getString(
- "DeploymentDisplay.loadUnitDialog.message",
- new Object[]{ce().getShortName(),
- ce().getUnusedString()}),
- Messages.getString("DeploymentDisplay.loadUnitDialog.title"),
- JOptionPane.QUESTION_MESSAGE, null, SharedUtility
+ Messages.getString(
+ "DeploymentDisplay.loadUnitDialog.message",
+ new Object[]{ce().getShortName(),
+ ce().getUnusedString()}),
+ Messages.getString("DeploymentDisplay.loadUnitDialog.title"),
+ JOptionPane.QUESTION_MESSAGE, null, SharedUtility
.getDisplayArray(choices), null);
choice = (Entity) SharedUtility.getTargetPicked(choices, input);
} else {
@@ -3163,7 +3165,7 @@ && ce().canLoad(other, false)) {
bayChoices = new ArrayList<>();
for (Transporter t : ce().getTransports()) {
if ((t instanceof ProtomechClampMount)
- && t.canLoad(choice)) {
+ && t.canLoad(choice)) {
bayChoices.add(((ProtomechClampMount) t).isRear() ? 1 : 0);
}
}
@@ -3171,9 +3173,9 @@ && ce().canLoad(other, false)) {
String[] retVal = new String[bayChoices.size()];
int i = 0;
for (Integer bn : bayChoices) {
- retVal[i++] = bn > 0?
+ retVal[i++] = bn > 0 ?
Messages.getString("MovementDisplay.loadProtoClampMountDialog.rear") :
- Messages.getString("MovementDisplay.loadProtoClampMountDialog.front");
+ Messages.getString("MovementDisplay.loadProtoClampMountDialog.front");
}
String bayString = (String) JOptionPane
.showInputDialog(
@@ -3233,11 +3235,11 @@ private Entity getTowedUnit() {
if (choices.size() > 1) {
String input = (String) JOptionPane
.showInputDialog(clientgui,
- Messages.getString(
- "DeploymentDisplay.towUnitDialog.message",
- new Object[]{ce().getShortName()}),
- Messages.getString("DeploymentDisplay.towUnitDialog.title"),
- JOptionPane.QUESTION_MESSAGE, null, SharedUtility
+ Messages.getString(
+ "DeploymentDisplay.towUnitDialog.message",
+ new Object[]{ce().getShortName()}),
+ Messages.getString("DeploymentDisplay.towUnitDialog.title"),
+ JOptionPane.QUESTION_MESSAGE, null, SharedUtility
.getDisplayArray(choices), null);
choice = (Entity) SharedUtility.getTargetPicked(choices, input);
} else {
@@ -3313,7 +3315,7 @@ public String toString() {
}
String selection = (String) JOptionPane.showInputDialog(clientgui,
Messages.getString("MovementDisplay.loadUnitHitchDialog.message",
- new Object[]{ce().getShortName()}),
+ new Object[]{ce().getShortName()}),
Messages.getString("MovementDisplay.loadUnitHitchDialog.title"),
JOptionPane.QUESTION_MESSAGE, null, retVal, null);
HitchChoice hc = null;
@@ -3367,7 +3369,7 @@ private Entity getDisconnectedUnit() {
clientgui,
Messages.getString(
"MovementDisplay.DisconnectUnitDialog.message", new Object[]{
- ce.getShortName(), ce.getUnusedString()}),
+ ce.getShortName(), ce.getUnusedString()}),
Messages.getString("MovementDisplay.DisconnectUnitDialog.title"),
JOptionPane.QUESTION_MESSAGE, null, SharedUtility
.getDisplayArray(towedUnits), null);
@@ -3465,12 +3467,12 @@ private Coords getUnloadPosition(Entity unloaded) {
choices[i++] = c.toString();
}
String selected = (String) JOptionPane.showInputDialog(clientgui,
- Messages.getString(
- "MovementDisplay.ChooseHex" + ".message", new Object[]{
- ce.getShortName(), ce.getUnusedString()}), Messages
- .getString("MovementDisplay.ChooseHex.title"),
+ Messages.getString(
+ "MovementDisplay.ChooseHex" + ".message", new Object[]{
+ ce.getShortName(), ce.getUnusedString()}), Messages
+ .getString("MovementDisplay.ChooseHex.title"),
- JOptionPane.QUESTION_MESSAGE, null, choices, null);
+ JOptionPane.QUESTION_MESSAGE, null, choices, null);
Coords choice = null;
if (selected == null) {
return choice;
@@ -3516,12 +3518,12 @@ private Coords getEjectPosition(Entity abandoned) {
choices[i++] = c.toString();
}
String selected = (String) JOptionPane.showInputDialog(clientgui,
- Messages.getString(
- "MovementDisplay.ChooseEjectHex.message", new Object[]{
- abandoned.getShortName(), abandoned.getUnusedString()}), Messages
- .getString("MovementDisplay.ChooseHex.title"),
+ Messages.getString(
+ "MovementDisplay.ChooseEjectHex.message", new Object[]{
+ abandoned.getShortName(), abandoned.getUnusedString()}), Messages
+ .getString("MovementDisplay.ChooseHex.title"),
- JOptionPane.QUESTION_MESSAGE, null, choices, null);
+ JOptionPane.QUESTION_MESSAGE, null, choices, null);
Coords choice = null;
if (selected == null) {
return choice;
@@ -3629,7 +3631,7 @@ private synchronized void updateJoinButton() {
if (game.useVectorMove()) {
// not where you are, but where you will be
loadeePos = Compute.getFinalPosition(ce.getPosition(),
- cmd.getFinalVectors());
+ cmd.getFinalVectors());
}
boolean isGood = false;
for (Entity other : game.getEntitiesVector(loadeePos)) {
@@ -3715,7 +3717,7 @@ private TreeMap> getLaunchedUnits() {
String question = Messages
.getString(
"MovementDisplay.LaunchFighterDialog.message", new Object[]{
- ce.getShortName(), doors * 2, bayNum});
+ ce.getShortName(), doors * 2, bayNum});
for (int loop = 0; loop < names.length; loop++) {
names[loop] = currentFighters.get(loop).getShortName();
}
@@ -3727,7 +3729,7 @@ private TreeMap> getLaunchedUnits() {
clientgui.frame,
Messages.getString(
"MovementDisplay.LaunchFighterDialog.title", new Object[]{
- currentBay.getType(), bayNum}), question,
+ currentBay.getType(), bayNum}), question,
names);
choiceDialog.setVisible(true);
if (choiceDialog.getChoices() == null) {
@@ -3875,42 +3877,42 @@ private TreeMap> getUndockedUnits() {
*
* @param craft The launching entity, which has already been tested to see if it's a small craft
*/
- private void loadPassengerAtLaunch(SmallCraft craft) {
- final Entity currentEntity = ce();
- if (currentEntity == null) {
- LogManager.getLogger().error("Cannot load passenger at launch for a null current entity.");
- return;
- }
-
- int space = 0;
- for (Bay b : craft.getTransportBays()) {
- if ((b instanceof CargoBay) || (b instanceof InfantryBay) || (b instanceof BattleArmorBay)) {
- // Assume a passenger takes up 0.1 tons per single infantryman weight calculations
- space += (int) Math.round(b.getUnused() / 0.1);
- }
- }
- // Passengers don't actually 'load' into bays to consume space, so update what's available for anyone
- // already aboard
- space -= ((craft.getTotalOtherCrew() + craft.getTotalPassengers()) * 0.1);
- // Make sure the text displays either the carrying capacity or the number of passengers left aboard
- space = Math.min(space, currentEntity.getNPassenger());
- ConfirmDialog takePassenger = new ConfirmDialog(clientgui.frame,
- Messages.getString("MovementDisplay.FillSmallCraftPassengerDialog.Title"),
- Messages.getString("MovementDisplay.FillSmallCraftPassengerDialog.message",
- craft.getShortName(), space, currentEntity.getShortName() + "'",
- currentEntity.getNPassenger()), false);
- takePassenger.setVisible(true);
- if (takePassenger.getAnswer()) {
- // Move the passengers
- currentEntity.setNPassenger(currentEntity.getNPassenger() - space);
- if (currentEntity instanceof Aero) {
- ((Aero) currentEntity).addEscapeCraft(craft.getExternalIdAsString());
- }
- clientgui.getClient().sendUpdateEntity(currentEntity);
- craft.addPassengers(currentEntity.getExternalIdAsString(), space);
- clientgui.getClient().sendUpdateEntity(craft);
- }
- }
+ private void loadPassengerAtLaunch(SmallCraft craft) {
+ final Entity currentEntity = ce();
+ if (currentEntity == null) {
+ LogManager.getLogger().error("Cannot load passenger at launch for a null current entity.");
+ return;
+ }
+
+ int space = 0;
+ for (Bay b : craft.getTransportBays()) {
+ if ((b instanceof CargoBay) || (b instanceof InfantryBay) || (b instanceof BattleArmorBay)) {
+ // Assume a passenger takes up 0.1 tons per single infantryman weight calculations
+ space += (int) Math.round(b.getUnused() / 0.1);
+ }
+ }
+ // Passengers don't actually 'load' into bays to consume space, so update what's available for anyone
+ // already aboard
+ space -= ((craft.getTotalOtherCrew() + craft.getTotalPassengers()) * 0.1);
+ // Make sure the text displays either the carrying capacity or the number of passengers left aboard
+ space = Math.min(space, currentEntity.getNPassenger());
+ ConfirmDialog takePassenger = new ConfirmDialog(clientgui.frame,
+ Messages.getString("MovementDisplay.FillSmallCraftPassengerDialog.Title"),
+ Messages.getString("MovementDisplay.FillSmallCraftPassengerDialog.message",
+ craft.getShortName(), space, currentEntity.getShortName() + "'",
+ currentEntity.getNPassenger()), false);
+ takePassenger.setVisible(true);
+ if (takePassenger.getAnswer()) {
+ // Move the passengers
+ currentEntity.setNPassenger(currentEntity.getNPassenger() - space);
+ if (currentEntity instanceof Aero) {
+ ((Aero) currentEntity).addEscapeCraft(craft.getExternalIdAsString());
+ }
+ clientgui.getClient().sendUpdateEntity(currentEntity);
+ craft.addPassengers(currentEntity.getExternalIdAsString(), space);
+ clientgui.getClient().sendUpdateEntity(craft);
+ }
+ }
/**
* Get the unit that the player wants to drop. This method will remove the
@@ -4595,18 +4597,18 @@ public synchronized void actionPerformed(ActionEvent ev) {
|| (gear == MovementDisplay.GEAR_CHARGE)
|| (gear == MovementDisplay.GEAR_DFA)
|| ((cmd.getMpUsed() > ce.getWalkMP())
- && !(cmd.getLastStep().isOnlyPavement()
- && (cmd.getMpUsed() <= (ce.getWalkMP() + 1))))
+ && !(cmd.getLastStep().isOnlyPavement()
+ && (cmd.getMpUsed() <= (ce.getWalkMP() + 1))))
|| (opts.booleanOption("tacops_tank_crews")
- && (cmd.getMpUsed() > 0) && (ce instanceof Tank)
- && (ce.getCrew().getSize() < 2))
+ && (cmd.getMpUsed() > 0) && (ce instanceof Tank)
+ && (ce.getCrew().getSize() < 2))
|| (gear == MovementDisplay.GEAR_SWIM)
|| (gear == MovementDisplay.GEAR_RAM)) {
// in the wrong gear
// clearAllMoves();
// gear = Compute.GEAR_LAND;
setUnjamEnabled(false);
- } else if (clientgui.doYesNoDialog(title, msg)) {
+ } else if (clientgui.doYesNoDialog(title, msg)) {
addStepToMovePath(MoveStepType.UNJAM_RAC);
isUnJammingRAC = true;
ready();
@@ -4633,8 +4635,8 @@ public synchronized void actionPerformed(ActionEvent ev) {
} else if (actionCmd.equals(MoveCommand.MOVE_JUMP.getCmd())) {
if ((gear != MovementDisplay.GEAR_JUMP)
&& !((cmd.getLastStep() != null)
- && cmd.getLastStep().isFirstStep()
- && (cmd.getLastStep().getType() == MoveStepType.LAY_MINE))) {
+ && cmd.getLastStep().isFirstStep()
+ && (cmd.getLastStep().getType() == MoveStepType.LAY_MINE))) {
clear();
}
if (!cmd.isJumping()) {
@@ -4712,7 +4714,7 @@ public synchronized void actionPerformed(ActionEvent ev) {
if (!clientgui.getClient().getGame()
.containsMinefield(ce.getPosition())) {
clientgui.doAlertDialog(Messages
- .getString("MovementDisplay.CantClearMinefield"),
+ .getString("MovementDisplay.CantClearMinefield"),
Messages.getString("MovementDisplay.NoMinefield"));
return;
}
@@ -4840,9 +4842,9 @@ public synchronized void actionPerformed(ActionEvent ev) {
// Dialog for choosing which location to brace
String option = (String) JOptionPane.showInputDialog(clientgui.getFrame(),
- "Choose the location to brace:",
- "Choose Brace Location", JOptionPane.QUESTION_MESSAGE, null,
- locationNames, locationNames[0]);
+ "Choose the location to brace:",
+ "Choose Brace Location", JOptionPane.QUESTION_MESSAGE, null,
+ locationNames, locationNames[0]);
// Verify that we have a valid option...
if (option != null) {
@@ -4853,20 +4855,20 @@ public synchronized void actionPerformed(ActionEvent ev) {
}
} else if (actionCmd.equals(MoveCommand.MOVE_FLEE.getCmd())
&& clientgui.doYesNoDialog(
- Messages.getString("MovementDisplay.EscapeDialog.title"),
- Messages.getString("MovementDisplay.EscapeDialog.message"))) {
+ Messages.getString("MovementDisplay.EscapeDialog.title"),
+ Messages.getString("MovementDisplay.EscapeDialog.message"))) {
clear();
addStepToMovePath(MoveStepType.FLEE);
ready();
} else if (actionCmd.equals(MoveCommand.MOVE_FLY_OFF.getCmd())
&& clientgui.doYesNoDialog(
- Messages.getString("MovementDisplay.FlyOffDialog.title"),
- Messages.getString("MovementDisplay.FlyOffDialog.message"))) {
+ Messages.getString("MovementDisplay.FlyOffDialog.title"),
+ Messages.getString("MovementDisplay.FlyOffDialog.message"))) {
if (opts.booleanOption(OptionsConstants.ADVAERORULES_RETURN_FLYOVER)
&& clientgui.doYesNoDialog(
- Messages.getString("MovementDisplay.ReturnFly.title"),
- Messages.getString("MovementDisplay.ReturnFly.message"))) {
+ Messages.getString("MovementDisplay.ReturnFly.title"),
+ Messages.getString("MovementDisplay.ReturnFly.message"))) {
addStepToMovePath(MoveStepType.RETURN);
} else {
addStepToMovePath(MoveStepType.OFF);
@@ -4959,7 +4961,7 @@ public synchronized void actionPerformed(ActionEvent ev) {
&& (cmd.getLastStep().getNDown() == 1)
&& (cmd.getLastStep().getVelocity() < 12)
&& !(((IAero) ce).isSpheroid() || clientgui.getClient()
- .getGame().getPlanetaryConditions().isVacuum())) {
+ .getGame().getPlanetaryConditions().isVacuum())) {
addStepToMovePath(MoveStepType.ACC, true);
}
addStepToMovePath(MoveStepType.DOWN);
@@ -4967,7 +4969,7 @@ public synchronized void actionPerformed(ActionEvent ev) {
MoveStep ms = cmd.getLastStep();
if ((ms != null)
&& ((ms.getType() == MoveStepType.CLIMB_MODE_ON) || (ms
- .getType() == MoveStepType.CLIMB_MODE_OFF))) {
+ .getType() == MoveStepType.CLIMB_MODE_OFF))) {
MoveStep lastStep = cmd.getLastStep();
cmd.removeLastStep();
// Add another climb mode step
@@ -5154,8 +5156,8 @@ public synchronized void actionPerformed(ActionEvent ev) {
String title = Messages.getString("MovementDisplay.NoTakeOffDialog.title");
String body = Messages.getString(
"MovementDisplay.NoTakeOffDialog.message",
- new Object[] { ((IAero) ce())
- .hasRoomForHorizontalTakeOff() });
+ new Object[]{((IAero) ce())
+ .hasRoomForHorizontalTakeOff()});
clientgui.doAlertDialog(title, body);
} else {
if (clientgui.doYesNoDialog(
@@ -5232,15 +5234,15 @@ public synchronized void actionPerformed(ActionEvent ev) {
if (idx == 0) {
JOptionPane.showMessageDialog(clientgui.getFrame(),
"No players available. Units cannot be traitored to players "
- + "that aren't assigned to a team.");
+ + "that aren't assigned to a team.");
return;
}
// Dialog for choosing which player to transfer to
String option = (String) JOptionPane.showInputDialog(clientgui.getFrame(),
- "Choose the player to gain ownership of this unit when it turns traitor",
- "Traitor", JOptionPane.QUESTION_MESSAGE, null,
- options, options[0]);
+ "Choose the player to gain ownership of this unit when it turns traitor",
+ "Traitor", JOptionPane.QUESTION_MESSAGE, null,
+ options, options[0]);
// Verify that we have a valid option...
if (option != null) {
@@ -5250,18 +5252,18 @@ public synchronized void actionPerformed(ActionEvent ev) {
// And now we perform the actual transfer
int confirm = JOptionPane.showConfirmDialog(
- clientgui.getFrame(),
- e.getDisplayName() + " will switch to " + name
- + "'s side at the end of this turn. Are you sure?",
- "Confirm",
- JOptionPane.YES_NO_OPTION);
+ clientgui.getFrame(),
+ e.getDisplayName() + " will switch to " + name
+ + "'s side at the end of this turn. Are you sure?",
+ "Confirm",
+ JOptionPane.YES_NO_OPTION);
if (confirm == JOptionPane.YES_OPTION) {
e.setTraitorId(id);
clientgui.getClient().sendUpdateEntity(e);
}
}
} else if (actionCmd.equals(MoveCommand.MOVE_CHAFF.getCmd())) {
- if(clientgui.doYesNoDialog(
+ if (clientgui.doYesNoDialog(
Messages.getString("MovementDisplay.ConfirmChaff.title"),
Messages.getString("MovementDisplay.ConfirmChaff.message"))) {
isUsingChaff = true;
diff --git a/megamek/src/megamek/client/ui/swing/PointblankShotDisplay.java b/megamek/src/megamek/client/ui/swing/PointblankShotDisplay.java
index 7cfd329c342..eeeea2152fc 100644
--- a/megamek/src/megamek/client/ui/swing/PointblankShotDisplay.java
+++ b/megamek/src/megamek/client/ui/swing/PointblankShotDisplay.java
@@ -635,7 +635,7 @@ public void ready() {
waa2.setAmmoId(waa.getAmmoId());
waa2.setAmmoMunitionType(waa.getAmmoMunitionType());
waa2.setAmmoCarrier(waa.getAmmoCarrier());
- waa2.setBombPayload(waa.getBombPayload());
+ waa2.setBombPayloads(waa.getBombPayloads());
waa2.setStrafing(waa.isStrafing());
waa2.setStrafingFirstShot(waa.isStrafingFirstShot());
waa2.setPointblankShot(waa.isPointblankShot());
@@ -669,7 +669,7 @@ public void ready() {
waa2.setAmmoId(waa.getAmmoId());
waa2.setAmmoMunitionType(waa.getAmmoMunitionType());
waa2.setAmmoCarrier(waa.getAmmoCarrier());
- waa2.setBombPayload(waa.getBombPayload());
+ waa2.setBombPayloads(waa.getBombPayloads());
waa2.setStrafing(waa.isStrafing());
waa2.setStrafingFirstShot(waa.isStrafingFirstShot());
waa2.setPointblankShot(waa.isPointblankShot());
diff --git a/megamek/src/megamek/client/ui/swing/QuirksPanel.java b/megamek/src/megamek/client/ui/swing/QuirksPanel.java
index d18f2f23804..1ee827ea79f 100644
--- a/megamek/src/megamek/client/ui/swing/QuirksPanel.java
+++ b/megamek/src/megamek/client/ui/swing/QuirksPanel.java
@@ -26,8 +26,10 @@
import megamek.client.ui.GBC;
import megamek.client.ui.Messages;
+import megamek.common.Aero;
import megamek.common.Entity;
import megamek.common.Mounted;
+import megamek.common.VTOL;
import megamek.common.options.IOption;
import megamek.common.options.IOptionGroup;
import megamek.common.options.Quirks;
@@ -126,6 +128,12 @@ public void setQuirks() {
option = comp.getOption();
if ((comp.getValue() == Messages.getString("CustomMechDialog.None"))) {
entity.getQuirks().getOption(option.getName()).setValue("None");
+ } else if (option.getName().equals("internal_bomb")) {
+ // Need to set the quirk, and only then force re-computing bomb bay space for Aero-derived units
+ entity.getQuirks().getOption(option.getName()).setValue(comp.getValue());
+ if (entity.isAero()) {
+ ((Aero) entity).autoSetMaxBombPoints();
+ }
} else {
entity.getQuirks().getOption(option.getName()).setValue(comp.getValue());
}
diff --git a/megamek/src/megamek/client/ui/swing/unitDisplay/SystemPanel.java b/megamek/src/megamek/client/ui/swing/unitDisplay/SystemPanel.java
index c9c892c6114..28f01b7b1ea 100644
--- a/megamek/src/megamek/client/ui/swing/unitDisplay/SystemPanel.java
+++ b/megamek/src/megamek/client/ui/swing/unitDisplay/SystemPanel.java
@@ -28,7 +28,7 @@
* This class shows the critical hits and systems for a mech
*/
class SystemPanel extends PicMap implements ItemListener, ActionListener, ListSelectionListener, IPreferenceChangeListener {
-
+
private static int LOC_ALL_EQUIP = 0;
private static int LOC_ALL_WEAPS = 1;
private static int LOC_SPACER = 2;
@@ -193,7 +193,7 @@ class SystemPanel extends PicMap implements ItemListener, ActionListener, ListSe
setBackGround();
onResize();
-
+
addListeners();
}
@@ -229,20 +229,20 @@ private CriticalSlot getSelectedCritical() {
private Mounted getSelectedEquipment() {
if ((locList.getSelectedIndex() == LOC_ALL_EQUIP)) {
- if (slotList.getSelectedIndex() != -1) {
+ if (slotList.getSelectedIndex() != -1) {
return en.getMisc().get(slotList.getSelectedIndex());
} else {
return null;
}
}
if (locList.getSelectedIndex() == LOC_ALL_WEAPS) {
- if (slotList.getSelectedIndex() != -1) {
+ if (slotList.getSelectedIndex() != -1) {
return en.getWeaponList().get(slotList.getSelectedIndex());
} else {
return null;
}
}
-
+
final CriticalSlot cs = getSelectedCritical();
if ((cs == null) || (unitDisplay.getClientGUI() == null)) {
return null;
@@ -307,7 +307,7 @@ public void displayMech(Entity newEntity) {
displayLocations();
addListeners();
}
-
+
public void selectLocation(int loc) {
locList.setSelectedIndex(loc + LOC_OFFSET);
}
@@ -333,10 +333,10 @@ private void displayLocations() {
private void displaySlots() {
int loc = locList.getSelectedIndex();
- DefaultListModel slotModel =
- ((DefaultListModel) slotList.getModel());
- slotModel.removeAllElements();
-
+ DefaultListModel slotModel =
+ ((DefaultListModel) slotList.getModel());
+ slotModel.removeAllElements();
+
// Display all Equipment
if (loc == LOC_ALL_EQUIP) {
for (Mounted m : en.getMisc()) {
@@ -344,7 +344,7 @@ private void displaySlots() {
}
return;
}
-
+
// Display all Weapons
if (loc == LOC_ALL_WEAPS) {
for (Mounted m : en.getWeaponList()) {
@@ -352,11 +352,11 @@ private void displaySlots() {
}
return;
}
-
+
// Display nothing for a spacer
if (loc == LOC_SPACER) {
return;
- }
+ }
// Standard location handling
loc -= LOC_OFFSET;
@@ -388,22 +388,22 @@ private void displaySlots() {
default:
}
if (cs.isArmored()) {
- sb.append(" (armored)");
+ sb.append(" (armored)");
}
}
slotModel.addElement(sb.toString());
}
onResize();
}
-
+
private String getMountedDisplay(Mounted m, int loc) {
return getMountedDisplay(m, loc, null);
}
-
+
private String getMountedDisplay(Mounted m, int loc, CriticalSlot cs) {
String hotLoaded = Messages.getString("MechDisplay.isHotLoaded");
StringBuffer sb = new StringBuffer();
-
+
sb.append(m.getDesc());
if ((cs != null) && cs.getMount2() != null) {
@@ -739,7 +739,7 @@ public void valueChanged(ListSelectionEvent event) {
&& (m.getUsableShotsLeft() > 0)
&& !m.isDumping()
&& en.isActive()
- && (client.getGame().getOptions().intOption(OptionsConstants.BASE_DUMPING_FROM_ROUND)
+ && (client.getGame().getOptions().intOption(OptionsConstants.BASE_DUMPING_FROM_ROUND)
<= client.getGame().getRoundCount())
&& !carryingBAsOnBack && !invalidEnvironment) {
m_bDumpAmmo.setEnabled(true);
@@ -822,21 +822,21 @@ public void valueChanged(ListSelectionEvent event) {
addListeners();
}
}
-
+
private void addListeners() {
locList.addListSelectionListener(this);
slotList.addListSelectionListener(this);
unitList.addListSelectionListener(this);
-
+
m_chMode.addItemListener(this);
m_bDumpAmmo.addActionListener(this);
}
-
+
private void removeListeners() {
locList.removeListSelectionListener(this);
slotList.removeListSelectionListener(this);
unitList.removeListSelectionListener(this);
-
+
m_chMode.removeItemListener(this);
m_bDumpAmmo.removeActionListener(this);
}
diff --git a/megamek/src/megamek/client/ui/swing/unitSelector/TWAdvancedSearchPanel.java b/megamek/src/megamek/client/ui/swing/unitSelector/TWAdvancedSearchPanel.java
index 23ad3a33fb1..34ed808bbe5 100644
--- a/megamek/src/megamek/client/ui/swing/unitSelector/TWAdvancedSearchPanel.java
+++ b/megamek/src/megamek/client/ui/swing/unitSelector/TWAdvancedSearchPanel.java
@@ -1071,13 +1071,13 @@ private JPanel createUnitTypePanel() {
filterAerospaceFighterPanel.add(btnFilterAerospaceFighter);
filterAerospaceFighterPanel.add(lblFilterAerospaceFighter);
unitTypePanel.add(filterAerospaceFighterPanel, c);
-
- c.gridy++;
- c.gridx = 1;
+ c.gridx = 2;
JPanel filterConvFighterPanel = new JPanel();
filterConvFighterPanel.add(btnFilterConvFighter);
filterConvFighterPanel.add(lblFilterConvFighter);
unitTypePanel.add(filterConvFighterPanel, c);
+
+ c.gridy++;
c.gridx = 2;
JPanel filterFixedWingSupportPanel = new JPanel();
filterFixedWingSupportPanel.add(btnFilterFixedWingSupport);
@@ -2450,7 +2450,7 @@ public Object getValueAt(int row, int col) {
if (row >= weaponClasses.size()) {
return null;
}
-
+
switch (col) {
case COL_QTY:
return qty[row] + "";
@@ -2976,7 +2976,7 @@ public boolean matches(String name) {
if (this == PHYSICAL) {
String lName = name.toLowerCase();
- if (lName.contains("backhoe") ||
+ if (lName.contains("backhoe") ||
lName.contains("saw") ||
lName.contains("whip") ||
lName.contains("claw") ||
@@ -3013,12 +3013,12 @@ public boolean matches(String name) {
}
} else if (this == MISSILE) {
if ((name.toLowerCase().contains("lrm") ||
- name.toLowerCase().contains("mrm") ||
- name.toLowerCase().contains("srm")) &&
+ name.toLowerCase().contains("mrm") ||
+ name.toLowerCase().contains("srm")) &&
!name.toLowerCase().contains("ammo")) {
return true;
}
- } else if (this == RE_ENGINEERED) {
+ } else if (this == RE_ENGINEERED) {
if (name.toLowerCase().contains("engineered")) {
return true;
}
@@ -3031,9 +3031,9 @@ public boolean matches(String name) {
return true;
}
} else if (this == BALLISTIC) {
- return WeaponClass.AUTOCANNON.matches(name) ||
- WeaponClass.GAUSS.matches(name) ||
- WeaponClass.MISSILE.matches(name) ||
+ return WeaponClass.AUTOCANNON.matches(name) ||
+ WeaponClass.GAUSS.matches(name) ||
+ WeaponClass.MISSILE.matches(name) ||
WeaponClass.MACHINE_GUN.matches(name);
} else if (this == RAC) {
if (name.toLowerCase().contains("rotary")) {
diff --git a/megamek/src/megamek/common/Aero.java b/megamek/src/megamek/common/Aero.java
index 6828e5c60eb..d77c3cafcb4 100644
--- a/megamek/src/megamek/common/Aero.java
+++ b/megamek/src/megamek/common/Aero.java
@@ -154,8 +154,12 @@ public String[] getLocationNames() {
// fixed and pod-mounted.
private int podHeatSinks;
- protected int maxBombPoints = 0;
- protected int[] bombChoices = new int[BombType.B_NUM];
+ protected int maxIntBombPoints = 0;
+ protected int maxExtBombPoints = 0;
+ protected int[] intBombChoices = new int[BombType.B_NUM];
+ protected int[] extBombChoices = new int[BombType.B_NUM];
+
+ protected int usedInternalBombs = 0;
// fuel - number of fuel points
private int fuel = 0;
@@ -477,33 +481,73 @@ public void setAccLast(boolean b) {
@Override
public int getMaxBombPoints() {
- return maxBombPoints;
+ return maxExtBombPoints + maxIntBombPoints;
+ }
+
+ @Override
+ public int getMaxIntBombPoints() {
+ return (hasQuirk(OptionsConstants.QUIRK_POS_INTERNAL_BOMB)) ? maxIntBombPoints : 0;
+ }
+
+ @Override
+ public int getMaxExtBombPoints() {
+ return maxExtBombPoints;
}
public void autoSetMaxBombPoints() {
- maxBombPoints = (int) Math.round(getWeight() / 5);
+ // Stock Aerospace units cannot carry bombs
+ maxExtBombPoints = maxIntBombPoints = 0;
}
@Override
- public int[] getBombChoices() {
- return bombChoices.clone();
+ public int[] getIntBombChoices() {
+ return intBombChoices.clone();
}
@Override
- public void setBombChoices(int[] bc) {
- if (bc.length == bombChoices.length) {
- bombChoices = bc;
+ public void setIntBombChoices(int[] bc) {
+ if (bc.length == intBombChoices.length) {
+ intBombChoices = bc.clone();
+ }
+ }
+
+ @Override
+ public int[] getExtBombChoices() {
+ return extBombChoices.clone();
+ }
+
+ @Override
+ public void setExtBombChoices(int[] bc) {
+ if (bc.length == extBombChoices.length) {
+ extBombChoices = bc.clone();
}
}
@Override
public void clearBombChoices() {
- Arrays.fill(bombChoices, 0);
+ Arrays.fill(intBombChoices, 0);
+ Arrays.fill(extBombChoices, 0);
}
@Override
public int reduceMPByBombLoad(int t) {
- return Math.max(0, t - (int) Math.ceil(getBombPoints() / 5.0));
+ // The base Aero cannot carry bombs so no MP reduction
+ return t;
+ }
+
+ @Override
+ public void setUsedInternalBombs(int b){
+ usedInternalBombs = b;
+ }
+
+ @Override
+ public void increaseUsedInternalBombs(int b){
+ usedInternalBombs += b;
+ }
+
+ @Override
+ public int getUsedInternalBombs() {
+ return usedInternalBombs;
}
public void setWhoFirst() {
@@ -985,6 +1029,9 @@ public void newRound(int roundNumber) {
setWhoFirst();
resetAltLossThisRound();
+
+ // Reset usedInternalBombs
+ setUsedInternalBombs(0);
}
/**
@@ -2726,34 +2773,6 @@ public void doDisbandDamage() {
}
}
- /**
- * Damage a capital fighter's weapons. WeaponGroups are damaged by critical hits.
- * This matches up the individual fighter's weapons and critical slots and damages those
- * for MHQ resolution
- * @param loc - Int corresponding to the location struck
- */
- public void damageCapFighterWeapons(int loc) {
- for (Mounted weapon : weaponList) {
- if (weapon.getLocation() == loc) {
- //Damage the weapon
- weapon.setHit(true);
- //Damage the critical slot
- for (int i = 0; i < getNumberOfCriticals(loc); i++) {
- CriticalSlot slot1 = getCritical(loc, i);
- if ((slot1 == null) ||
- (slot1.getType() == CriticalSlot.TYPE_SYSTEM)) {
- continue;
- }
- Mounted mounted = slot1.getMount();
- if (mounted.equals(weapon)) {
- hitAllCriticals(loc, i);
- break;
- }
- }
- }
- }
- }
-
/**
* @return The total number of crew available to supplement marines on boarding actions.
* Includes officers, enlisted, and bay personnel, but not marines/ba or passengers.
@@ -2990,7 +3009,7 @@ public long getEntityType() {
}
public boolean isInASquadron() {
- return game.getEntity(getTransportId()) instanceof FighterSquadron;
+ return false;
}
@Override
@@ -2998,9 +3017,14 @@ public boolean isAero() {
return true;
}
+ /**
+ * Fighters may carry external ordnance;
+ * Other Aerospace units with cargo bays and the Internal Bomb Bay quirk may carry bombs internally.
+ * @return boolean
+ */
@Override
public boolean isBomber() {
- return isFighter();
+ return false;
}
@Override
@@ -3009,7 +3033,7 @@ public boolean isBomber() {
* but not a larger craft (i.e. "SmallCraft" or "Dropship" and bigger
*/
public boolean isFighter() {
- return true;
+ return false;
}
@Override
@@ -3017,7 +3041,7 @@ public boolean isFighter() {
* Returns true if and only if this is an aerospace fighter.
*/
public boolean isAerospaceFighter() {
- return true;
+ return false;
}
@Override
diff --git a/megamek/src/megamek/common/AeroSpaceFighter.java b/megamek/src/megamek/common/AeroSpaceFighter.java
new file mode 100644
index 00000000000..98be7c4f8d7
--- /dev/null
+++ b/megamek/src/megamek/common/AeroSpaceFighter.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2024 - The MegaMek Team. All Rights Reserved.
+ *
+ * This file is part of MegaMek.
+ *
+ * MegaMek is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MegaMek is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MegaMek. If not, see .
+ */
+
+package megamek.common;
+
+import megamek.client.ui.swing.calculationReport.CalculationReport;
+import megamek.common.cost.AeroCostCalculator;
+import megamek.common.enums.AimingMode;
+import megamek.common.options.OptionsConstants;
+import org.apache.logging.log4j.LogManager;
+
+import java.text.NumberFormat;
+import java.util.*;
+
+/**
+ * AeroSpaceFighter subclass of Aero that encapsulates Fighter functionality
+ */
+public class AeroSpaceFighter extends Aero {
+ public AeroSpaceFighter() {
+ super();
+ }
+
+ @Override
+ public int getUnitType() {
+ return UnitType.AEROSPACEFIGHTER;
+ }
+
+ @Override
+ public void autoSetMaxBombPoints() {
+ // Aerospace fighters can carry both external and internal ordnances, if configured and quirked
+ // appropriately
+ maxExtBombPoints = (int) Math.round(getWeight() / 5);
+ // Can't check quirk here, as they don't exist in unit files yet.
+ maxIntBombPoints = getTransportBays().stream().mapToInt(
+ tb -> (tb instanceof CargoBay) ? (int) Math.floor(tb.getUnused()) : 0
+ ).sum();
+ }
+
+ @Override
+ public boolean isInASquadron() {
+ return game.getEntity(getTransportId()) instanceof FighterSquadron;
+ }
+
+ @Override
+ public int reduceMPByBombLoad(int t) {
+ return Math.max(0, t - (int) Math.ceil(getExternalBombPoints() / 5.0));
+ }
+
+ @Override
+ public boolean isSpheroid() {
+ return false;
+ }
+
+ // Damage a fighter that was part of a squadron when splitting it. Per
+ // StratOps pg. 32 & 34
+ @Override
+ public void doDisbandDamage() {
+
+ int dealt = 0;
+
+ // Check for critical threshold and if so damage all armor on one facing
+ // of the fighter completely,
+ // reduce SI by half, and mark three engine hits.
+ if (isDestroyed() || isDoomed()) {
+ int loc = Compute.randomInt(4);
+ dealt = getArmor(loc);
+ setArmor(0, loc);
+ int finalSI = Math.min(getSI(), getSI() / 2);
+ dealt += getSI() - finalSI;
+ setSI(finalSI);
+ setEngineHits(Math.max(3, getEngineHits()));
+ }
+
+ // Move on to actual damage...
+ int damage = getCap0Armor() - getCapArmor();
+ // Fix for #587. Only multiply if Aero Sanity is off
+ if ((null != game) && !game.getOptions().booleanOption(OptionsConstants.ADVAERORULES_AERO_SANITY)) {
+ damage *= 10;
+ }
+ damage -= dealt; // We already dealt a bunch of damage, move on.
+ if (damage < 1) {
+ return;
+ }
+ int hits = (int) Math.ceil(damage / 5.0);
+ int damPerHit = 5;
+ for (int i = 0; i < hits; i++) {
+ int loc = Compute.randomInt(4);
+ // Fix for #587. Apply in 5 point groups unless damage remainder is less.
+ setArmor(getArmor(loc) - Math.min(damPerHit, damage), loc);
+ // We did too much damage, so we need to damage the SI, but we wont
+ // reduce the SI below 1 here
+ // unless the fighter is destroyed.
+ if (getArmor(loc) < 0) {
+ if (getSI() > 1) {
+ int si = getSI() + (getArmor(loc) / 2);
+ si = Math.max(si, isDestroyed() || isDoomed() ? 0 : 1);
+ setSI(si);
+ }
+ setArmor(0, loc);
+ }
+ damage -= damPerHit;
+ }
+ }
+
+ /**
+ * Damage a capital fighter's weapons. WeaponGroups are damaged by critical hits.
+ * This matches up the individual fighter's weapons and critical slots and damages those
+ * for MHQ resolution
+ * @param loc - Int corresponding to the location struck
+ */
+ public void damageCapFighterWeapons(int loc) {
+ for (Mounted weapon : weaponList) {
+ if (weapon.getLocation() == loc) {
+ //Damage the weapon
+ weapon.setHit(true);
+ //Damage the critical slot
+ for (int i = 0; i < getNumberOfCriticals(loc); i++) {
+ CriticalSlot slot1 = getCritical(loc, i);
+ if ((slot1 == null) ||
+ (slot1.getType() == CriticalSlot.TYPE_SYSTEM)) {
+ continue;
+ }
+ Mounted mounted = slot1.getMount();
+ if (mounted.equals(weapon)) {
+ hitAllCriticals(loc, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isAero() {
+ return true;
+ }
+
+ @Override
+ public boolean isBomber() {
+ return true;
+ }
+
+ @Override
+ public boolean isFighter() {
+ return true;
+ }
+
+ @Override
+ public boolean isAerospaceFighter() {
+ return true;
+ }
+
+ @Override
+ public long getEntityType() {
+ return super.getEntityType() | Entity.ETYPE_AEROSPACEFIGHTER;
+ }
+}
diff --git a/megamek/src/megamek/common/AmmoType.java b/megamek/src/megamek/common/AmmoType.java
index e307cc292bd..a8e6d423406 100644
--- a/megamek/src/megamek/common/AmmoType.java
+++ b/megamek/src/megamek/common/AmmoType.java
@@ -146,11 +146,11 @@ public class AmmoType extends EquipmentType {
* Contains the {@code AmmoType}s that could share ammo (e.g. SRM 2 and SRM 6,
* both fire SRM rounds).
*/
- private static final Integer[] ALLOWED_BY_TYPE_ARRAY = { AmmoType.T_LRM, AmmoType.T_LRM_PRIMITIVE,
+ private static final Integer[] ALLOWED_BY_TYPE_ARRAY = {AmmoType.T_LRM, AmmoType.T_LRM_PRIMITIVE,
AmmoType.T_LRM_STREAK, AmmoType.T_LRM_TORPEDO, AmmoType.T_LRM_TORPEDO_COMBO, AmmoType.T_SRM,
AmmoType.T_SRM_ADVANCED, AmmoType.T_SRM_PRIMITIVE, AmmoType.T_SRM_STREAK, AmmoType.T_SRM_TORPEDO,
AmmoType.T_MRM, AmmoType.T_ROCKET_LAUNCHER, AmmoType.T_EXLRM, AmmoType.T_MML, AmmoType.T_NLRM, AmmoType.T_MG, AmmoType.T_MG_LIGHT, AmmoType.T_MG_HEAVY,
- AmmoType.T_NAIL_RIVET_GUN, AmmoType.T_ATM, AmmoType.T_IATM, };
+ AmmoType.T_NAIL_RIVET_GUN, AmmoType.T_ATM, AmmoType.T_IATM,};
/**
* Contains the set of {@code AmmoType}s which could share ammo (e.g. SRM 2 and
@@ -190,10 +190,13 @@ public class AmmoType extends EquipmentType {
// Used by MHQ for loading ammo bins
public static final BigInteger F_SCREEN = BigInteger.valueOf(1).shiftLeft(18);
+ // Used for Internal Bomb Bay bombs; to differentiate them from
+ public static final BigInteger F_INTERNAL_BOMB = BigInteger.valueOf(1).shiftLeft(19);
+
// ammo munitions, used for custom loadouts
// N.B. We use EnumSet allow "incendiary"
// to be combined to other munition types.
- public enum Munitions{
+ public enum Munitions {
M_STANDARD,
// AC Munition Types
@@ -425,8 +428,8 @@ public boolean isCompatibleWith(AmmoType other) {
// ATM Launchers
if (((is(T_ATM) && other.is(T_IATM)) || (is(T_IATM) && other.is(T_ATM))) && (getMunitionType() == other.getMunitionType())) {
- // Ammo exclusive to iATMs couldn't have the same munition type as standard ATMs
- return true;
+ // Ammo exclusive to iATMs couldn't have the same munition type as standard ATMs
+ return true;
}
// General Launchers
@@ -460,11 +463,11 @@ public boolean is(int ammoType) {
public boolean countsAsFlak() {
boolean counts = false;
- if(ArrayUtils.contains(ARTILLERY_TYPES, this.getAmmoType())){
+ if (ArrayUtils.contains(ARTILLERY_TYPES, this.getAmmoType())) {
// Air-Defense Arrow IV _is_ Flak, but is _not_ Artillery
counts = ARTILLERY_FLAK_MUNITIONS.containsAll(this.getMunitionType())
|| this.getMunitionType().contains(Munitions.M_ADA);
- } else if(ArrayUtils.contains(ARTILLERY_CANNON_TYPES, this.getAmmoType())){
+ } else if (ArrayUtils.contains(ARTILLERY_CANNON_TYPES, this.getAmmoType())) {
counts = this.getMunitionType().contains(Munitions.M_STANDARD);
}
return counts;
@@ -2328,13 +2331,13 @@ public static void initializeTypes() {
// Create the munition types for IS Arrow IV launchers.
munitions.clear();
munitions.add(new MunitionMutator("Air-Defense Arrow (ADA) Missiles", 1, Munitions.M_ADA,
- new TechAdvancement(TECH_BASE_IS).setIntroLevel(false).setUnofficial(false)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setPrototypeFactions(F_CC)
- .setISAdvancement(3068, 3080, DATE_NONE, DATE_NONE, DATE_NONE)
- .setApproximate(false, false, false, false, false).setTechRating(RATING_E)
- .setProductionFactions(F_CC).setStaticTechLevel(SimpleTechLevel.ADVANCED)
- , "165, TO:AU&E"));
+ new TechAdvancement(TECH_BASE_IS).setIntroLevel(false).setUnofficial(false)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setPrototypeFactions(F_CC)
+ .setISAdvancement(3068, 3080, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setApproximate(false, false, false, false, false).setTechRating(RATING_E)
+ .setProductionFactions(F_CC).setStaticTechLevel(SimpleTechLevel.ADVANCED)
+ , "165, TO:AU&E"));
munitions.add(new MunitionMutator("Cluster", 1, Munitions.M_CLUSTER,
new TechAdvancement(TECH_BASE_IS).setIntroLevel(false).setUnofficial(false).setTechRating(RATING_E)
@@ -2765,7 +2768,7 @@ public static void initializeTypes() {
AmmoType.createMunitions(clanHeavyFlamerAmmos, munitions);
// cache types that share a launcher for loadout purposes
- for (Enumeration e = EquipmentType.getAllTypes(); e.hasMoreElements();) {
+ for (Enumeration e = EquipmentType.getAllTypes(); e.hasMoreElements(); ) {
EquipmentType et = e.nextElement();
if (!(et instanceof AmmoType)) {
continue;
@@ -2991,13 +2994,13 @@ private static AmmoType createISCruiseMissile50Ammo() {
ammo.rulesRefs = "284, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS)
- .setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
- .setISApproximate(false, true, false, false, false)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.ADVANCED);
+ .setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setISApproximate(false, true, false, false, false)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.ADVANCED);
return ammo;
}
@@ -3017,13 +3020,13 @@ private static AmmoType createISCruiseMissile70Ammo() {
ammo.rulesRefs = "284, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS)
- .setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
- .setISApproximate(false, true, false, false, false)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.ADVANCED);
+ .setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setISApproximate(false, true, false, false, false)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.ADVANCED);
return ammo;
}
@@ -3043,13 +3046,13 @@ private static AmmoType createISCruiseMissile90Ammo() {
ammo.rulesRefs = "284, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS)
- .setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
- .setISApproximate(false, true, false, false, false)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.ADVANCED);
+ .setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setISApproximate(false, true, false, false, false)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.ADVANCED);
return ammo;
}
@@ -3069,13 +3072,13 @@ private static AmmoType createISCruiseMissile120Ammo() {
ammo.rulesRefs = "284, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS)
- .setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
- .setISApproximate(false, true, false, false, false)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.ADVANCED);
+ .setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3065, 3095, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setISApproximate(false, true, false, false, false)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.ADVANCED);
return ammo;
}
@@ -3106,9 +3109,9 @@ private static AmmoType createISLongTomCannonAmmo() {
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_ALL).setTechRating(RATING_B)
.setAvailability(RATING_X, RATING_F, RATING_E, RATING_D)
- .setISAdvancement(3012, 3079, DATE_NONE, DATE_NONE,DATE_NONE)
+ .setISAdvancement(3012, 3079, DATE_NONE, DATE_NONE, DATE_NONE)
.setISApproximate(false, true, false, false, false)
- .setClanAdvancement(3032, 3079, DATE_NONE, DATE_NONE,DATE_NONE)
+ .setClanAdvancement(3032, 3079, DATE_NONE, DATE_NONE, DATE_NONE)
.setClanApproximate(false, true, false, false, false)
.setPrototypeFactions(F_LC, F_CWF)
.setProductionFactions(F_LC)
@@ -3160,9 +3163,9 @@ private static AmmoType createISSniperCannonAmmo() {
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_ALL).setTechRating(RATING_B)
.setAvailability(RATING_X, RATING_F, RATING_E, RATING_D)
- .setISAdvancement(3012, 3079, DATE_NONE, DATE_NONE,DATE_NONE)
+ .setISAdvancement(3012, 3079, DATE_NONE, DATE_NONE, DATE_NONE)
.setISApproximate(false, true, false, false, false)
- .setClanAdvancement(3032, 3079, DATE_NONE, DATE_NONE,DATE_NONE)
+ .setClanAdvancement(3032, 3079, DATE_NONE, DATE_NONE, DATE_NONE)
.setClanApproximate(false, true, false, false, false)
.setPrototypeFactions(F_LC, F_CWF)
.setProductionFactions(F_LC)
@@ -3215,9 +3218,9 @@ private static AmmoType createISThumperCannonAmmo() {
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_ALL).setTechRating(RATING_B)
.setAvailability(RATING_X, RATING_F, RATING_E, RATING_D)
- .setISAdvancement(3012, 3079, DATE_NONE, DATE_NONE,DATE_NONE)
+ .setISAdvancement(3012, 3079, DATE_NONE, DATE_NONE, DATE_NONE)
.setISApproximate(false, true, false, false, false)
- .setClanAdvancement(3032, 3079, DATE_NONE, DATE_NONE,DATE_NONE)
+ .setClanAdvancement(3032, 3079, DATE_NONE, DATE_NONE, DATE_NONE)
.setClanApproximate(false, true, false, false, false)
.setPrototypeFactions(F_LC, F_CWF)
.setProductionFactions(F_LC)
@@ -3438,7 +3441,7 @@ private static AmmoType createCLPROAC2Ammo() {
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN)
.setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setClanAdvancement(DATE_NONE, 3070, 3073, DATE_NONE,DATE_NONE)
+ .setClanAdvancement(DATE_NONE, 3070, 3073, DATE_NONE, DATE_NONE)
.setClanApproximate(false, true, false, false, false)
.setPrototypeFactions(F_CBS).setProductionFactions(F_CBS)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
@@ -3464,7 +3467,7 @@ private static AmmoType createCLPROAC4Ammo() {
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN)
.setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setClanAdvancement(DATE_NONE, 3070, 3073, DATE_NONE,DATE_NONE)
+ .setClanAdvancement(DATE_NONE, 3070, 3073, DATE_NONE, DATE_NONE)
.setClanApproximate(false, true, false, false, false)
.setPrototypeFactions(F_CBS).setProductionFactions(F_CBS)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
@@ -3490,7 +3493,7 @@ private static AmmoType createCLPROAC8Ammo() {
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN)
.setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setClanAdvancement(DATE_NONE, 3070, 3073, DATE_NONE,DATE_NONE)
+ .setClanAdvancement(DATE_NONE, 3070, 3073, DATE_NONE, DATE_NONE)
.setClanApproximate(false, true, false, false, false)
.setPrototypeFactions(F_CBS).setProductionFactions(F_CBS)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
@@ -4230,11 +4233,11 @@ private static AmmoType createCLRotary2Ammo() {
ammo.rulesRefs = "286, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setClanAdvancement(3073, DATE_NONE, 3104, DATE_NONE, DATE_NONE)
- .setClanApproximate(false, false, false, false, false)
- .setPrototypeFactions(F_CSF).setProductionFactions(F_CSF)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setClanAdvancement(3073, DATE_NONE, 3104, DATE_NONE, DATE_NONE)
+ .setClanApproximate(false, false, false, false, false)
+ .setPrototypeFactions(F_CSF).setProductionFactions(F_CSF)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -4255,11 +4258,11 @@ private static AmmoType createCLRotary5Ammo() {
ammo.rulesRefs = "286, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setClanAdvancement(3073, DATE_NONE, 3104, DATE_NONE, DATE_NONE)
- .setClanApproximate(false, false, false, false, false)
- .setPrototypeFactions(F_CSF).setProductionFactions(F_CSF)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setClanAdvancement(3073, DATE_NONE, 3104, DATE_NONE, DATE_NONE)
+ .setClanApproximate(false, false, false, false, false)
+ .setPrototypeFactions(F_CSF).setProductionFactions(F_CSF)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -4280,10 +4283,10 @@ private static AmmoType createISLightRifleAmmo() {
ammo.rulesRefs = "338, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_B)
- .setAvailability(RATING_C, RATING_F, RATING_X, RATING_D)
- .setISAdvancement(DATE_PS, DATE_NONE, 3084, DATE_NONE, DATE_NONE)
- .setISApproximate(false, false, true, false, false)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ .setAvailability(RATING_C, RATING_F, RATING_X, RATING_D)
+ .setISAdvancement(DATE_PS, DATE_NONE, 3084, DATE_NONE, DATE_NONE)
+ .setISApproximate(false, false, true, false, false)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -4304,10 +4307,10 @@ private static AmmoType createISMediumRifleAmmo() {
ammo.rulesRefs = "338, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_B)
- .setAvailability(RATING_C, RATING_F, RATING_X, RATING_D)
- .setISAdvancement(DATE_PS, DATE_NONE, 3084, DATE_NONE, DATE_NONE)
- .setISApproximate(false, false, true, false, false)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ .setAvailability(RATING_C, RATING_F, RATING_X, RATING_D)
+ .setISAdvancement(DATE_PS, DATE_NONE, 3084, DATE_NONE, DATE_NONE)
+ .setISApproximate(false, false, true, false, false)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -4328,10 +4331,10 @@ private static AmmoType createISHeavyRifleAmmo() {
ammo.rulesRefs = "338, TO";
//Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_B)
- .setAvailability(RATING_C, RATING_F, RATING_X, RATING_D)
- .setISAdvancement(DATE_PS, DATE_NONE, 3084, DATE_NONE, DATE_NONE)
- .setISApproximate(false, false, true, false, false)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ .setAvailability(RATING_C, RATING_F, RATING_X, RATING_D)
+ .setISAdvancement(DATE_PS, DATE_NONE, 3084, DATE_NONE, DATE_NONE)
+ .setISApproximate(false, false, true, false, false)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -5526,10 +5529,10 @@ private static AmmoType createCLIATM6Ammo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5551,10 +5554,10 @@ private static AmmoType createCLIATM9Ammo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5576,10 +5579,10 @@ private static AmmoType createCLIATM12Ammo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5603,10 +5606,10 @@ private static AmmoType createCLIATM3ERAmmo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5628,10 +5631,10 @@ private static AmmoType createCLIATM6ERAmmo() {
ammo.flags = ammo.flags.or(F_HOTLOAD);
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5654,10 +5657,10 @@ private static AmmoType createCLIATM9ERAmmo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5680,10 +5683,10 @@ private static AmmoType createCLIATM12ERAmmo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5707,10 +5710,10 @@ private static AmmoType createCLIATM3HEAmmo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5733,10 +5736,10 @@ private static AmmoType createCLIATM6HEAmmo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5759,10 +5762,10 @@ private static AmmoType createCLIATM9HEAmmo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -5785,10 +5788,10 @@ private static AmmoType createCLIATM12HEAmmo() {
ammo.setModes("", "HotLoad");
ammo.rulesRefs = "65, IO";
ammo.techAdvancement.setTechBase(TECH_BASE_CLAN).setIntroLevel(false).setUnofficial(false)
- .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
- .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
- .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
- .setProductionFactions(F_CCY);
+ .setTechRating(RATING_F).setAvailability(RATING_X, RATING_X, RATING_D, RATING_D)
+ .setClanAdvancement(3054, 3070, DATE_NONE, DATE_NONE, DATE_NONE)
+ .setClanApproximate(true, false, false, false, false).setPrototypeFactions(F_CCY)
+ .setProductionFactions(F_CCY);
return ammo;
}
@@ -6146,12 +6149,12 @@ private static AmmoType createISEnhancedLRM5Ammo() {
ammo.cost = 31000;
ammo.rulesRefs = "326, TO";
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
- ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3058,DATE_NONE, 3082,DATE_NONE,DATE_NONE)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3058, DATE_NONE, 3082, DATE_NONE, DATE_NONE)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -6172,12 +6175,12 @@ private static AmmoType createISEnhancedLRM10Ammo() {
ammo.cost = 31000;
ammo.rulesRefs = "326, TO";
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
- ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3058,DATE_NONE, 3082,DATE_NONE,DATE_NONE)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3058, DATE_NONE, 3082, DATE_NONE, DATE_NONE)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -6197,12 +6200,12 @@ private static AmmoType createISEnhancedLRM15Ammo() {
ammo.cost = 31000;
ammo.rulesRefs = "326, TO";
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
- ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3058,DATE_NONE, 3082,DATE_NONE,DATE_NONE)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3058, DATE_NONE, 3082, DATE_NONE, DATE_NONE)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -6222,12 +6225,12 @@ private static AmmoType createISEnhancedLRM20Ammo() {
ammo.cost = 31000;
ammo.rulesRefs = "326, TO";
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
- ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
- .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(3058,DATE_NONE, 3082,DATE_NONE,DATE_NONE)
- .setPrototypeFactions(F_FS)
- .setProductionFactions(F_FS)
- .setStaticTechLevel(SimpleTechLevel.STANDARD);
+ ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
+ .setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
+ .setISAdvancement(3058, DATE_NONE, 3082, DATE_NONE, DATE_NONE)
+ .setPrototypeFactions(F_FS)
+ .setProductionFactions(F_FS)
+ .setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
}
@@ -6255,7 +6258,7 @@ private static AmmoType createISExtendedLRM5Ammo() {
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
.setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(DATE_NONE, 3054, 3080,DATE_NONE, DATE_NONE)
+ .setISAdvancement(DATE_NONE, 3054, 3080, DATE_NONE, DATE_NONE)
.setPrototypeFactions(F_FS, F_LC).setProductionFactions(F_LC)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
@@ -6284,7 +6287,7 @@ private static AmmoType createISExtendedLRM10Ammo() {
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
.setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(DATE_NONE, 3054, 3080,DATE_NONE, DATE_NONE)
+ .setISAdvancement(DATE_NONE, 3054, 3080, DATE_NONE, DATE_NONE)
.setPrototypeFactions(F_FS, F_LC).setProductionFactions(F_LC)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
@@ -6313,7 +6316,7 @@ private static AmmoType createISExtendedLRM15Ammo() {
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
.setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(DATE_NONE, 3054, 3080,DATE_NONE, DATE_NONE)
+ .setISAdvancement(DATE_NONE, 3054, 3080, DATE_NONE, DATE_NONE)
.setPrototypeFactions(F_FS, F_LC).setProductionFactions(F_LC)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
@@ -6342,7 +6345,7 @@ private static AmmoType createISExtendedLRM20Ammo() {
// Tech Progression tweaked to combine IntOps with TRO Prototypes/3145 NTNU RS
ammo.techAdvancement.setTechBase(TECH_BASE_IS).setTechRating(RATING_E)
.setAvailability(RATING_X, RATING_X, RATING_F, RATING_E)
- .setISAdvancement(DATE_NONE, 3054, 3080,DATE_NONE, DATE_NONE)
+ .setISAdvancement(DATE_NONE, 3054, 3080, DATE_NONE, DATE_NONE)
.setPrototypeFactions(F_FS, F_LC).setProductionFactions(F_LC)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
return ammo;
@@ -7402,7 +7405,7 @@ private static AmmoType createCLLRM19Ammo() {
}
-//Standard MRMs
+ //Standard MRMs
private static AmmoType createISMRM10Ammo() {
AmmoType ammo = new AmmoType();
@@ -12273,7 +12276,7 @@ private static AmmoType createISCoolantPod() {
ammo.cost = 50000;
// TODO : modes is a bodge because there is no proper end phase
- String[] theModes = { "safe", "efficient", "off", "dump" };
+ String[] theModes = {"safe", "efficient", "off", "dump"};
ammo.setModes(theModes);
ammo.setInstantModeSwitch(true);
ammo.rulesRefs = "303, TO";
@@ -12768,7 +12771,6 @@ private static AmmoType createISRailGunAmmo() {
}
-
private static AmmoType createISAC10iAmmo() {
AmmoType ammo = new AmmoType();
@@ -13037,8 +13039,8 @@ public static boolean canClearMinefield(AmmoType at) {
|| (at.getAmmoType() == T_ROCKET_LAUNCHER))
&& (at.getRackSize() >= 20)
&& ((at.getMunitionType().contains(Munitions.M_STANDARD)) || (at.getMunitionType().contains(Munitions.M_ARTEMIS_CAPABLE))
- || (at.getMunitionType().contains(Munitions.M_ARTEMIS_V_CAPABLE))
- || (at.getMunitionType().contains(Munitions.M_NARC_CAPABLE)))) {
+ || (at.getMunitionType().contains(Munitions.M_ARTEMIS_V_CAPABLE))
+ || (at.getMunitionType().contains(Munitions.M_NARC_CAPABLE)))) {
return true;
}
// ATMs
@@ -13060,11 +13062,11 @@ public static boolean canClearMinefield(AmmoType at) {
public static boolean canDeliverMinefield(AmmoType at) {
return (at != null)
&& ((at.getAmmoType() == T_LRM) || (at.getAmmoType() == AmmoType.T_LRM_IMP)
- || (at.getAmmoType() == AmmoType.T_MML))
+ || (at.getAmmoType() == AmmoType.T_MML))
&& ((at.getMunitionType().contains(Munitions.M_THUNDER)) || (at.getMunitionType().contains(Munitions.M_THUNDER_INFERNO))
- || (at.getMunitionType().contains(Munitions.M_THUNDER_AUGMENTED))
- || (at.getMunitionType().contains(Munitions.M_THUNDER_VIBRABOMB))
- || (at.getMunitionType().contains(Munitions.M_THUNDER_ACTIVE)));
+ || (at.getMunitionType().contains(Munitions.M_THUNDER_AUGMENTED))
+ || (at.getMunitionType().contains(Munitions.M_THUNDER_VIBRABOMB))
+ || (at.getMunitionType().contains(Munitions.M_THUNDER_ACTIVE)));
}
private void addToEnd(AmmoType base, String modifier) {
@@ -13481,7 +13483,7 @@ public AmmoType createMunitionType(AmmoType base) {
|| (munition.getAmmoType() == AmmoType.T_MML) || (munition.getAmmoType() == AmmoType.T_SRM)
|| (munition.getAmmoType() == AmmoType.T_SRM_IMP) || (munition.getAmmoType() == AmmoType.T_NLRM))
&& ((munition.getMunitionType().contains(Munitions.M_ANTI_TSM))
- || (munition.getMunitionType().contains(Munitions.M_FRAGMENTATION)))) {
+ || (munition.getMunitionType().contains(Munitions.M_FRAGMENTATION)))) {
cost *= 2;
}
@@ -13496,7 +13498,7 @@ public AmmoType createMunitionType(AmmoType base) {
if (((munition.getAmmoType() == AmmoType.T_MML) || (munition.getAmmoType() == AmmoType.T_SRM)
|| (munition.getAmmoType() == AmmoType.T_SRM_IMP))
&& ((munition.getMunitionType().contains(Munitions.M_TANDEM_CHARGE))
- || (munition.getMunitionType().contains(Munitions.M_ARTEMIS_V_CAPABLE)))) {
+ || (munition.getMunitionType().contains(Munitions.M_ARTEMIS_V_CAPABLE)))) {
cost *= 5;
bv *= 2;
}
@@ -13505,7 +13507,7 @@ public AmmoType createMunitionType(AmmoType base) {
|| (munition.getAmmoType() == AmmoType.T_MML) || (munition.getAmmoType() == AmmoType.T_SRM)
|| (munition.getAmmoType() == AmmoType.T_SRM_IMP) || (munition.getAmmoType() == AmmoType.T_NLRM))
&& ((munition.getMunitionType().contains(Munitions.M_HEAT_SEEKING))
- || (munition.getMunitionType().contains(Munitions.M_FOLLOW_THE_LEADER)))) {
+ || (munition.getMunitionType().contains(Munitions.M_FOLLOW_THE_LEADER)))) {
cost *= 2;
bv *= 1.5;
}
diff --git a/megamek/src/megamek/common/Compute.java b/megamek/src/megamek/common/Compute.java
index a0edc3e7c6f..684e38bf8b3 100644
--- a/megamek/src/megamek/common/Compute.java
+++ b/megamek/src/megamek/common/Compute.java
@@ -22,6 +22,7 @@
import megamek.common.enums.BasementType;
import megamek.common.enums.IlluminationLevel;
import megamek.common.options.OptionsConstants;
+import megamek.common.weapons.DiveBombAttack;
import megamek.common.weapons.InfantryAttack;
import megamek.common.weapons.Weapon;
import megamek.common.weapons.artillery.ArtilleryCannonWeapon;
@@ -3848,6 +3849,14 @@ public static boolean isInArc(Game game, int attackerId, int weaponId,
}
}
+ // Allow dive-bombing VTOLs to attack the hex they are in, if they didn't select one for bombing while moving.
+ if ((ae.getMovementMode() == EntityMovementMode.VTOL)
+ && aPos.equals(tPos)) {
+ if (ae.getEquipment(weaponId).getType().hasFlag(WeaponType.F_DIVE_BOMB)) {
+ return true;
+ }
+ }
+
// if using advanced AA options, then ground-to-air fire determines arc
// by closest position
if (isGroundToAir(ae, t) && (t instanceof Entity)) {
diff --git a/megamek/src/megamek/common/ConvFighter.java b/megamek/src/megamek/common/ConvFighter.java
index 65d26666126..63c37a96db3 100644
--- a/megamek/src/megamek/common/ConvFighter.java
+++ b/megamek/src/megamek/common/ConvFighter.java
@@ -21,7 +21,7 @@
* @author Jay Lawson
* @since Jun 12, 2008
*/
-public class ConvFighter extends Aero {
+public class ConvFighter extends AeroSpaceFighter {
private static final long serialVersionUID = 6297668284292929409L;
@Override
@@ -53,7 +53,7 @@ public boolean doomedInSpace() {
public int getHeatCapacity() {
return DOES_NOT_TRACK_HEAT;
}
-
+
@Override
public boolean tracksHeat() {
return false;
@@ -84,12 +84,12 @@ public int getFuelUsed(int thrust) {
.setAdvancement(DATE_NONE, 2470, 2490).setProductionFactions(F_TH)
.setTechRating(RATING_D).setAvailability(RATING_C, RATING_D, RATING_C, RATING_B)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
-
+
@Override
public TechAdvancement getConstructionTechAdvancement() {
return TA_CONV_FIGHTER;
}
-
+
@Override
public double getBVTypeModifier() {
return 1.1;
diff --git a/megamek/src/megamek/common/Dropship.java b/megamek/src/megamek/common/Dropship.java
index c04f709f116..62412655b36 100644
--- a/megamek/src/megamek/common/Dropship.java
+++ b/megamek/src/megamek/common/Dropship.java
@@ -25,11 +25,11 @@
*/
public class Dropship extends SmallCraft {
private static final long serialVersionUID = 1528728632696989565L;
-
+
// ASEW Missile Effects, per location
// Values correspond to Locations: NOS, Left, Right, AFT
private int[] asewAffectedTurns = { 0, 0, 0, 0 };
-
+
/**
* Sets the number of rounds a specified firing arc is affected by an ASEW missile
* @param arc - integer representing the desired firing arc
@@ -41,14 +41,14 @@ public void setASEWAffected(int arc, int turns) {
asewAffectedTurns[arc] = turns;
}
}
-
+
/**
* Returns the number of rounds a specified firing arc is affected by an ASEW missile
* @param arc - integer representing the desired firing arc
*/
public int getASEWAffected(int arc) {
if (arc < asewAffectedTurns.length) {
- return asewAffectedTurns[arc];
+ return asewAffectedTurns[arc];
}
return 0;
}
@@ -59,15 +59,15 @@ public int getASEWAffected(int arc) {
public static final int COLLAR_STANDARD = 0;
public static final int COLLAR_PROTOTYPE = 1;
public static final int COLLAR_NO_BOOM = 2;
-
+
private static final String[] COLLAR_NAMES = {
"KF-Boom", "Prototype KF-Boom", "No Boom"
};
-
+
// Likewise, you can have a prototype or standard K-F Boom
public static final int BOOM_STANDARD = 0;
public static final int BOOM_PROTOTYPE = 1;
-
+
// what needs to go here?
// loading and unloading of units?
private boolean dockCollarDamaged = false;
@@ -106,39 +106,39 @@ public CrewType defaultCrewType() {
public boolean isDockCollarDamaged() {
return dockCollarDamaged;
}
-
+
public int getCollarType() {
return collarType;
}
-
+
public void setCollarType(int collarType) {
this.collarType = collarType;
}
-
+
public String getCollarName() {
return COLLAR_NAMES[collarType];
}
-
+
public static String getCollarName(int type) {
return COLLAR_NAMES[type];
}
-
+
public static TechAdvancement getCollarTA() {
return new TechAdvancement(TECH_BASE_ALL).setAdvancement(2458, 2470, 2500)
.setPrototypeFactions(F_TH).setProductionFactions(F_TH).setTechRating(RATING_C)
.setAvailability(RATING_C, RATING_C, RATING_C, RATING_C)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
}
-
+
//KF Boom Stuff
public boolean isKFBoomDamaged() {
return kfBoomDamaged;
}
-
+
public int getBoomType() {
return boomType;
}
-
+
public void setBoomType(int boomType) {
this.boomType = boomType;
}
@@ -257,26 +257,26 @@ public boolean isLocationProhibited(Coords c, int currElevation) {
return isProhibited;
}
-
+
/**
* Worker function that checks if a given hex contains terrain onto which a grounded dropship
- * cannot deploy.
+ * cannot deploy.
*/
private boolean hexContainsProhibitedTerrain(Hex hex) {
return hex.containsTerrain(Terrains.WOODS) || hex.containsTerrain(Terrains.ROUGH)
|| ((hex.terrainLevel(Terrains.WATER) > 0) && !hex.containsTerrain(Terrains.ICE))
|| hex.containsTerrain(Terrains.RUBBLE) || hex.containsTerrain(Terrains.MAGMA)
|| hex.containsTerrain(Terrains.JUNGLE) || (hex.terrainLevel(Terrains.SNOW) > 1)
- || (hex.terrainLevel(Terrains.GEYSER) == 2)
- || hex.containsTerrain(Terrains.BUILDING) || hex.containsTerrain(Terrains.IMPASSABLE)
+ || (hex.terrainLevel(Terrains.GEYSER) == 2)
+ || hex.containsTerrain(Terrains.BUILDING) || hex.containsTerrain(Terrains.IMPASSABLE)
|| hex.containsTerrain(Terrains.BRIDGE);
-
+
}
public void setDamageDockCollar(boolean b) {
dockCollarDamaged = b;
}
-
+
public void setDamageKFBoom(boolean b) {
kfBoomDamaged = b;
}
@@ -332,7 +332,7 @@ public double getStrategicFuelUse() {
}
return fuelUse;
}
-
+
@Override
public double primitiveFuelFactor() {
int year = getOriginalBuildYear();
@@ -364,12 +364,12 @@ public double primitiveFuelFactor() {
.setProductionFactions(F_TA).setTechRating(RATING_D)
.setAvailability(RATING_D, RATING_X, RATING_X, RATING_X)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
-
+
@Override
public TechAdvancement getConstructionTechAdvancement() {
return isPrimitive() ? TA_DROPSHIP_PRIMITIVE : TA_DROPSHIP;
}
-
+
@Override
protected void addSystemTechAdvancement(CompositeTechLevel ctl) {
super.addSystemTechAdvancement(ctl);
@@ -377,7 +377,7 @@ protected void addSystemTechAdvancement(CompositeTechLevel ctl) {
ctl.addComponent(getCollarTA());
}
}
-
+
@Override
public double getCost(CalculationReport calcReport, boolean ignoreAmmo) {
return DropShipCostCalculator.calculateCost(this, calcReport, ignoreAmmo);
@@ -677,11 +677,11 @@ public long getEntityType() {
@Override
public boolean canChangeSecondaryFacing() {
- // flying dropships can execute the "ECHO" maneuver (stratops 113), aka a torso twist,
+ // flying dropships can execute the "ECHO" maneuver (stratops 113), aka a torso twist,
// if they have the MP for it
return isAirborne() && !isEvading() && (mpUsed <= getRunMP() - 2);
}
-
+
/**
* Can this dropship "torso twist" in the given direction?
*/
@@ -694,7 +694,7 @@ public boolean isValidSecondaryFacing(int dir) {
}
return rotate == 0;
}
-
+
/**
* Return the nearest valid direction to "torso twist" in
*/
@@ -703,29 +703,29 @@ public int clipSecondaryFacing(int dir) {
if (isValidSecondaryFacing(dir)) {
return dir;
}
-
+
// can't twist without enough MP
if (!canChangeSecondaryFacing()) {
return getFacing();
}
-
+
// otherwise, twist once in the appropriate direction
final int rotate = (dir + (6 - getFacing())) % 6;
-
+
return rotate >= 3 ? (getFacing() + 5) % 6 : (getFacing() + 1) % 6;
}
-
+
@Override
public void newRound(int roundNumber) {
super.newRound(roundNumber);
-
+
if (getGame().useVectorMove()) {
setFacing(getSecondaryFacing());
}
-
+
setSecondaryFacing(getFacing());
}
-
+
/**
* Utility function that handles situations where a facing change
* has some kind of permanent effect on the entity.
diff --git a/megamek/src/megamek/common/Entity.java b/megamek/src/megamek/common/Entity.java
index 829e75ecc2f..68ccab5bf4f 100644
--- a/megamek/src/megamek/common/Entity.java
+++ b/megamek/src/megamek/common/Entity.java
@@ -770,6 +770,7 @@ public abstract class Entity extends TurnOrdered implements Transporter, Targeta
protected int consecutiveRHSUses = 0;
private final Set attackedByThisTurn = Collections.newSetFromMap(new ConcurrentHashMap<>());
+ private final Set groundAttackedByThisTurn = Collections.newSetFromMap(new ConcurrentHashMap<>());
/**
* Determines the sort order for weapons in the UnitDisplay weapon list.
@@ -4183,6 +4184,11 @@ protected void resetBombAttacks() {
if (eq.getType().equals(spaceBomb) || eq.getType().equals(altBomb)
|| eq.getType().equals(diveBomb)) {
bombAttacksToRemove.add(eq);
+ } else if (eq.getLinked() != null && eq.getLinked().isInternalBomb()){
+ // Remove any used internal bombs
+ if (eq.getLinked().getUsableShotsLeft() <= 0) {
+ bombAttacksToRemove.add(eq);
+ }
}
}
equipmentList.removeAll(bombAttacksToRemove);
@@ -12976,17 +12982,39 @@ public void setInitialBV(int bv) {
* @return
*/
public int[] getBombLoadout() {
+ return getBombLoadout(false);
+ }
+
+ public int[] getBombLoadout(boolean internalOnly) {
int[] loadout = new int[BombType.B_NUM];
for (Mounted bomb : getBombs()) {
if ((bomb.getUsableShotsLeft() > 0)
&& (bomb.getType() instanceof BombType)) {
- int type = ((BombType) bomb.getType()).getBombType();
- loadout[type] = loadout[type] + 1;
+ // Either count all bombs, or just internal bombs
+ if (internalOnly && !bomb.isInternalBomb()) {
+ continue;
+ } else {
+ int type = ((BombType) bomb.getType()).getBombType();
+ loadout[type] = loadout[type] + 1;
+ }
}
}
return loadout;
}
+ public int[] getInternalBombLoadout() {
+ return getBombLoadout(true);
+ }
+
+ public int[] getExternalBombLoadout() {
+ int[] allBombs = getBombLoadout();
+ int[] intBombs = getBombLoadout(true);
+ for (int i = 0; i < allBombs.length; i++) {
+ allBombs[i] -= intBombs[i];
+ }
+ return allBombs;
+ }
+
@Override
public Map getSecondaryPositions() {
return secondaryPositions;
@@ -14459,14 +14487,25 @@ public void addAttackedByThisTurn(int entityId) {
attackedByThisTurn.add(entityId);
}
+ public void addGroundAttackedByThisTurn(int entityId) {
+ groundAttackedByThisTurn.add(entityId);
+ }
+
public void clearAttackedByThisTurn() {
attackedByThisTurn.clear();
+ if (groundAttackedByThisTurn != null) {
+ groundAttackedByThisTurn.clear();
+ }
}
public Collection getAttackedByThisTurn() {
return new HashSet<>(attackedByThisTurn);
}
+ public Collection getGroundAttackedByThisTurn() {
+ return new HashSet<>(groundAttackedByThisTurn);
+ }
+
public WeaponSortOrder getWeaponSortOrder() {
return (weaponSortOrder == null) ? WeaponSortOrder.DEFAULT : weaponSortOrder;
}
diff --git a/megamek/src/megamek/common/EntityListFile.java b/megamek/src/megamek/common/EntityListFile.java
index 331c27ea563..6121971f525 100644
--- a/megamek/src/megamek/common/EntityListFile.java
+++ b/megamek/src/megamek/common/EntityListFile.java
@@ -858,16 +858,26 @@ private static void writeEntityList(Writer output, ArrayList list) throw
// Write the Bomb Data if needed
if (entity.isBomber()) {
IBomber b = (IBomber) entity;
- int[] bombChoices = b.getBombChoices();
- if (bombChoices.length > 0) {
+ int[] intBombChoices = b.getIntBombChoices();
+ int[] extBombChoices = b.getExtBombChoices();
+ if (intBombChoices.length > 0 || extBombChoices.length > 0) {
output.write(indentStr(indentLvl + 1) + "\n");
for (int type = 0; type < BombType.B_NUM; type++) {
String typeName = BombType.getBombInternalName(type);
- if (bombChoices[type] > 0) {
+ if (intBombChoices[type] > 0) {
output.write(indentStr(indentLvl + 2) + "\n");
+ }
+ if (extBombChoices[type] > 0) {
+ output.write(indentStr(indentLvl + 2) + "\n");
}
}
@@ -879,6 +889,8 @@ private static void writeEntityList(Writer output, ArrayList list) throw
output.write(m.getType().getShortName());
output.write("\" load=\"");
output.write(String.valueOf(m.getBaseShotsLeft()));
+ output.write("\" Internal=\"");
+ output.write(String.valueOf(m.isInternalBomb()));
output.write("\"/>\n");
}
output.write(indentStr(indentLvl + 1) + "\n");
diff --git a/megamek/src/megamek/common/EntityWeightClass.java b/megamek/src/megamek/common/EntityWeightClass.java
index 60a72307d0a..542939b6c73 100644
--- a/megamek/src/megamek/common/EntityWeightClass.java
+++ b/megamek/src/megamek/common/EntityWeightClass.java
@@ -71,6 +71,8 @@ public class EntityWeightClass {
public static double[] getWeightLimitByType(String type) {
if (type.equals(UnitType.getTypeName(UnitType.MEK))) {
return mechWeightLimits;
+ } else if (type.equals(UnitType.getTypeName(UnitType.AEROSPACEFIGHTER))) {
+ return ASFWeightLimits;
} else if (type.equals(UnitType.getTypeName(UnitType.AERO))) {
return ASFWeightLimits;
} else if (type.equals(UnitType.getTypeName(UnitType.BATTLE_ARMOR))) {
@@ -150,7 +152,7 @@ public static int getWeightClass(double tonnage, String type) {
}
} else if (type.equals(UnitType.getTypeName(UnitType.SMALL_CRAFT))) {
return WEIGHT_SMALL_CRAFT;
- } else if (type.equals("Aero") || type.equals("Conventional Fighter")) {
+ } else if (type.equals("AeroSpaceFighter") || type.equals("Aero") || type.equals("Conventional Fighter")) {
for (i = WEIGHT_LIGHT; i < (ASFWeightLimits.length - 1); i++) { // Started late to bypass padding & save a loop execution
if (tonnage <= ASFWeightLimits[i]) {
break;
diff --git a/megamek/src/megamek/common/FighterSquadron.java b/megamek/src/megamek/common/FighterSquadron.java
index 7a95e66ce43..c0dc1dbd8d0 100644
--- a/megamek/src/megamek/common/FighterSquadron.java
+++ b/megamek/src/megamek/common/FighterSquadron.java
@@ -33,7 +33,7 @@
* Fighter squadrons are basically "containers" for a bunch of fighters.
* @author Jay Lawson
*/
-public class FighterSquadron extends Aero {
+public class FighterSquadron extends AeroSpaceFighter {
private static final long serialVersionUID = 3491212296982370726L;
public static final int MAX_SIZE = 6;
@@ -42,7 +42,7 @@ public class FighterSquadron extends Aero {
public static final int ALTERNATE_MAX_SIZE = 10;
private static final Predicate ACTIVE_CHECK = ent -> !((ent == null) || ent.isDestroyed() || ent.isDoomed());
-
+
private final List fighters = new ArrayList<>();
// fighter squadrons need to keep track of heat capacity apart from their fighters
@@ -145,7 +145,7 @@ public int getFuel() {
.min()
.orElse(0);
}
-
+
@Override
public int getCurrentFuel() {
return getActiveSubEntities().stream()
@@ -253,7 +253,7 @@ public int doBattleValueCalculation(boolean ignoreC3, boolean ignoreSkill, Calcu
public int getHeatSinks() {
return getActiveSubEntities().stream().mapToInt(ent -> ((IAero) ent).getHeatSinks()).sum();
}
-
+
@Override
public int getHeatCapacity(final boolean includeRadicalHeatSink) {
return includeRadicalHeatSink ? heatCapacity : heatCapacityNoRHS;
@@ -274,13 +274,13 @@ public double getWeight() {
public HitData rollHitLocation(int table, int side, int aimedLocation, AimingMode aimingMode,
int cover) {
List activeFighters = getActiveSubEntities();
-
+
// If this squadron is doomed or is of size 1 then just return the first one
if (isDoomed() || (activeFighters.size() <= 1)) {
return new HitData(0);
}
- // Pick a random number between 0 and the number of fighters in the squadron.
+ // Pick a random number between 0 and the number of fighters in the squadron.
int hit = Compute.randomInt(activeFighters.size());
return new HitData(hit);
}
@@ -299,7 +299,7 @@ public void newRound(int roundNumber) {
updateSkills();
resetHeatCapacity();
}
-
+
/**
* Update sensors. Use the active sensor of the first fighter in the squadron that hasn't taken 3 sensor hits
* BAPs don't count as active sensors in space, but they do make detection rolls easier
@@ -322,7 +322,7 @@ public void updateSensors() {
}
setNextSensor(getSensors().firstElement());
break;
- }
+ }
}
}
}
@@ -440,18 +440,24 @@ public void useFuel(int fuel) {
@Override
public void autoSetMaxBombPoints() {
- maxBombPoints = Integer.MAX_VALUE;
+ maxExtBombPoints = maxIntBombPoints = Integer.MAX_VALUE;
for (Entity fighter : getSubEntities()) {
+ // External bomb points
int currBombPoints = (int) Math.round(fighter.getWeight() / 5);
- maxBombPoints = Math.min(maxBombPoints, currBombPoints);
+ maxExtBombPoints = Math.min(maxExtBombPoints, currBombPoints);
+ // Internal (cargo bay) bomb points; requires IBB to utilize
+ currBombPoints = getTransportBays().stream().mapToInt(
+ tb -> (tb instanceof CargoBay) ? (int) Math.floor(tb.getUnused()) : 0
+ ).sum();
+ maxIntBombPoints = Math.min(maxIntBombPoints, currBombPoints);
}
}
@Override
public void setBombChoices(int... bc) {
// Set the bombs for the squadron
- if (bc.length == bombChoices.length) {
- bombChoices = bc;
+ if (bc.length == extBombChoices.length) {
+ extBombChoices = bc;
}
// Update each fighter in the squadron
for (Entity bomber : getSubEntities()) {
@@ -492,7 +498,7 @@ public void applyBombs() {
* This method looks at the bombs equipped on all the fighters in the
* squadron and determines what possible bombing attacks the squadrons
* can make.
- *
+ *
* TODO: Make this into a generic "clean up bomb loadout" method
*/
public void computeSquadronBombLoadout() {
@@ -515,13 +521,13 @@ public void computeSquadronBombLoadout() {
}
maxBombCount = Math.max(bombCount, maxBombCount);
}
- bombChoices[btype] = maxBombCount;
+ extBombChoices[btype] = maxBombCount;
}
// Now that we know our bomb choices, load 'em
int gameTL = TechConstants.getSimpleLevel(game.getOptions().stringOption("techlevel"));
for (int type = 0; type < BombType.B_NUM; type++) {
- for (int i = 0; i < bombChoices[type]; i++) {
+ for (int i = 0; i < extBombChoices[type]; i++) {
if ((type == BombType.B_ALAMO)
&& !game.getOptions().booleanOption(OptionsConstants.ADVAERORULES_AT2_NUKES)) {
continue;
@@ -551,7 +557,7 @@ public void computeSquadronBombLoadout() {
}
}
// Clear out the bomb choice once the bombs are loaded
- bombChoices[type] = 0;
+ extBombChoices[type] = 0;
}
// add the space bomb attack
if (game.getOptions().booleanOption(OptionsConstants.ADVAERORULES_STRATOPS_SPACE_BOMB)
@@ -684,14 +690,14 @@ public int getCargoMpReduction(Entity carrier) {
@Override
public long getEntityType() {
- return Entity.ETYPE_AERO | Entity.ETYPE_FIGHTER_SQUADRON;
+ return super.getEntityType() | Entity.ETYPE_FIGHTER_SQUADRON;
}
@Override
public Engine getEngine() {
return null;
}
-
+
@Override
public boolean hasEngine() {
return false;
@@ -700,11 +706,11 @@ public boolean hasEngine() {
@Override
public EntityMovementMode getMovementMode() {
List entities = getSubEntities();
-
+
if (entities.size() < 1) {
return EntityMovementMode.NONE;
}
-
+
EntityMovementMode moveMode = entities.get(0).getMovementMode();
for (Entity fighter : entities) {
if (moveMode != fighter.getMovementMode()) {
@@ -714,14 +720,14 @@ public EntityMovementMode getMovementMode() {
}
return moveMode;
}
-
+
@Override
public List getSubEntities() {
return fighters.stream().map(fid -> game.getEntity(fid))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
-
+
@Override
public List getActiveSubEntities() {
return fighters.stream().map(fid -> game.getEntity(fid))
diff --git a/megamek/src/megamek/common/FixedWingSupport.java b/megamek/src/megamek/common/FixedWingSupport.java
index a4e878c9a6a..2b28db6685d 100644
--- a/megamek/src/megamek/common/FixedWingSupport.java
+++ b/megamek/src/megamek/common/FixedWingSupport.java
@@ -13,6 +13,7 @@
import megamek.client.ui.swing.calculationReport.CalculationReport;
import megamek.common.cost.FixedWingSupportCostCalculator;
+import megamek.common.options.OptionsConstants;
/**
* @author Jason Tighe
@@ -234,14 +235,20 @@ protected int calculateWalk() {
@Override
public void autoSetMaxBombPoints() {
- // fixed wing support craft need external stores hardpoints to be able to carry bombs
+ // fixed wing support craft need external stores hardpoints or the Internal Bomb Bay quirk
+ // to be able to carry bombs.
int bombpoints = 0;
for (Mounted misc : getMisc()) {
if (misc.getType().hasFlag(MiscType.F_EXTERNAL_STORES_HARDPOINT)) {
bombpoints++;
}
}
- maxBombPoints = bombpoints;
+ maxExtBombPoints = bombpoints;
+
+ // fixed-wing support craft may also use internal transport bays as bomb bays with Internal Bomb Bay quirk.
+ maxIntBombPoints = getTransportBays().stream().mapToInt(
+ tb -> (tb instanceof CargoBay) ? (int) Math.floor(tb.getUnused()) : 0
+ ).sum();
}
@Override
diff --git a/megamek/src/megamek/common/IAero.java b/megamek/src/megamek/common/IAero.java
index baf5da77177..6c902f85af4 100644
--- a/megamek/src/megamek/common/IAero.java
+++ b/megamek/src/megamek/common/IAero.java
@@ -170,9 +170,10 @@ default boolean requiresFuel() {
void autoSetCapArmor();
void autoSetFatalThresh();
-
+
int getAltitude();
+
/**
* Iterate through current weapons and count the number in each capital
* fighter location.
diff --git a/megamek/src/megamek/common/IBomber.java b/megamek/src/megamek/common/IBomber.java
index ea42e39496a..202dbbcba44 100644
--- a/megamek/src/megamek/common/IBomber.java
+++ b/megamek/src/megamek/common/IBomber.java
@@ -20,48 +20,107 @@
import java.util.Arrays;
import java.util.List;
+import java.util.stream.IntStream;
import megamek.common.options.OptionsConstants;
/**
* Common interface for all entities capable of carrying bombs and making bomb attacks, includig Aero,
* LandAirMech, and VTOL.
- *
+ *
* @author Neoancient
*/
public interface IBomber {
-
+
String SPACE_BOMB_ATTACK = "SpaceBombAttack";
String DIVE_BOMB_ATTACK = "DiveBombAttack";
String ALT_BOMB_ATTACK = "AltBombAttack";
+ /**
+ * Set count of internal bombs used; this is used to reset, revert, or increase count
+ * of internal bombs a unit has dropped during a turn.
+ * @param b
+ */
+ void setUsedInternalBombs(int b);
+
+ /**
+ * Increase count of internal bombs used this turn.
+ * @param b
+ */
+ void increaseUsedInternalBombs(int b);
+
+ /**
+ * @return the number of internal bombs used by this bomber during a turn, for
+ * IBB internal hit calculations.
+ */
+ int getUsedInternalBombs();
+
+
/**
* @return The total number of bomb points that the bomber can carry.
*/
int getMaxBombPoints();
-
+
/**
- * Fighters and VTOLs can carry any size bomb up to the maximum number of points, but LAMs are limited
- * to the number of bays in a single location.
- *
- * @return The largest single bomb that can be carried
+ * Fighters and VTOLs can carry any size bomb up to the maximum number of points per location (internal/external),
+ * but LAMs are limited to the number of bays in a single location.
+ *
+ * @return The largest single bomb that can be carried internally.
*/
- default int getMaxBombSize() {
- return getMaxBombPoints();
+ default int getMaxIntBombSize() {
+ return getMaxIntBombPoints();
}
-
+
/**
- * @return The number of each bomb type that was selected prior to deployment
+ *
+ * @return The largest single bomb that can be carried externally.
*/
- int[] getBombChoices();
-
+ default int getMaxExtBombSize() {
+ return getMaxExtBombPoints();
+ }
+
+ /**
+ * @return The number of each internally-mounted bomb type that was selected prior to deployment
+ */
+ int[] getIntBombChoices();
+
+ /**
+ * @return The number of each externally-mounted bomb type that was selected prior to deployment
+ */
+ int[] getExtBombChoices();
+
/**
* Sets the bomb type selections prior to deployment.
- *
+ *
+ * @param bc An array with the count of each bomb type as the value of the bomb type's index
+ */
+ void setIntBombChoices(int[] bc);
+
+ /**
+ * Sets the bomb type selections for external mounts.
* @param bc An array with the count of each bomb type as the value of the bomb type's index
*/
- void setBombChoices(int[] bc);
-
+ void setExtBombChoices(int[] bc);
+
+ /**
+ * @return summed combination of internal and external choices
+ */
+ default int[] getBombChoices(){
+ int[] intArr = getIntBombChoices();
+ int[] extArr = getExtBombChoices();
+ IntStream range = IntStream.range(0, Math.min(intArr.length, extArr.length));
+ IntStream stream3 = range.map(i -> intArr[i] + extArr[i]);
+ return stream3.toArray();
+ }
+
+ /**
+ * Backwards compatibility bomb choice setter that only affects external stores.
+ * @param ebc
+ */
+ default void setBombChoices(int[] ebc) {
+ setExtBombChoices(ebc);
+ }
+
/**
* Sets the count of each bomb to zero
*/
@@ -71,7 +130,7 @@ default int getMaxBombSize() {
* @return The calculates movement factoring in the load of bombs currently on unit, t is current movement
*/
int reduceMPByBombLoad(int t);
-
+
/**
* @param cost The cost of the bomb to be mounted
* @return A location with sufficient space to mount the bomb, or Entity.LOC_NONE if the unit does not have the space.
@@ -96,18 +155,52 @@ default boolean isVTOLBombing() {
List getBombs();
/**
- * @return The number of points taken up by all mounted bombs or other external stores.
+ *
+ * @return the number of total bomb points for this unit
*/
default int getBombPoints() {
+ return getBombPoints(false);
+ }
+
+ /**
+ *
+ * @return the number of externally-mounted ordnance points (useful for MP calculations)
+ */
+ default int getExternalBombPoints() {
+ return getBombPoints(true);
+ }
+
+ /**
+ *
+ * @return total damage from remaining bombs
+ */
+ default int getInternalBombsDamageTotal() {
+ int total = 0;
+ for (Mounted bomb: getBombs()) {
+ if (bomb.isInternalBomb()) {
+ total += bomb.getExplosionDamage();
+ }
+ }
+
+ return total;
+ }
+
+ /**
+ * @return The number of points taken up by all mounted bombs, or just external
+ */
+ default int getBombPoints(boolean externalOnly) {
int points = 0;
for (Mounted bomb : getBombs()) {
if (bomb.getUsableShotsLeft() > 0) {
- points += BombType.getBombCost(((BombType) bomb.getType()).getBombType());
+ // Add points if A) not external only, and any kind of bomb, or B) external only, and not internal bomb
+ points += !(externalOnly && bomb.isInternalBomb()) ?
+ BombType.getBombCost(((BombType) bomb.getType()).getBombType()) : 0;
}
}
return points;
}
+
/**
* Iterate through the bomb choices that were configured prior to deployment and add the corresponding
* equipment.
@@ -115,15 +208,20 @@ default int getBombPoints() {
default void applyBombs() {
Game game = ((Entity) this).getGame();
int gameTL = TechConstants.getSimpleLevel(game.getOptions().stringOption("techlevel"));
- Integer[] sorted = new Integer[BombType.B_NUM];
+ Integer[] iSorted = new Integer[BombType.B_NUM];
// Apply the largest bombs first because we need to fit larger bombs into a single location
// in LAMs.
- for (int i = 0; i < sorted.length; i++) {
- sorted[i] = i;
+ for (int i = 0; i < iSorted.length; i++) {
+ iSorted[i] = i;
}
- Arrays.sort(sorted, (a, b) -> BombType.bombCosts[b] - BombType.bombCosts[a]);
- for (int type : sorted) {
- for (int i = 0; i < getBombChoices()[type]; i++) {
+ Integer[] eSorted = iSorted.clone();
+
+ Arrays.sort(iSorted, (a, b) -> BombType.bombCosts[b] - BombType.bombCosts[a]);
+ Arrays.sort(eSorted, (a, b) -> BombType.bombCosts[b] - BombType.bombCosts[a]);
+
+ // First, internal bombs
+ for (int type : iSorted) {
+ for (int i = 0; i < getIntBombChoices()[type]; i++) {
int loc = availableBombLocation(BombType.bombCosts[type]);
if ((type == BombType.B_ALAMO)
&& !game.getOptions().booleanOption(OptionsConstants.ADVAERORULES_AT2_NUKES)) {
@@ -137,34 +235,91 @@ default void applyBombs() {
// some bombs need an associated weapon and if so
// they need a weapon for each bomb
if (null != BombType.getBombWeaponName(type)) {
- Mounted m;
- try {
- m = ((Entity) this).addBomb(EquipmentType.get(BombType
- .getBombWeaponName(type)), loc);
- // Add bomb itself as single-shot ammo.
- if (type != BombType.B_TAG) {
- Mounted ammo = new Mounted((Entity) this,
- EquipmentType.get(BombType.getBombInternalName(type)));
- ammo.setShotsLeft(1);
- m.setLinked(ammo);
- ((Entity) this).addEquipment(ammo, loc, false);
-
- }
- } catch (LocationFullException ignored) {
-
- }
+ applyBombWeapons(type, loc, true);
} else {
- try {
- ((Entity) this).addEquipment(EquipmentType.get(BombType.getBombInternalName(type)),
- loc, false);
- } catch (LocationFullException ignored) {
+ applyBombEquipment(type, loc, true);
+ }
+ }
+ }
- }
+ // Now external bombs
+ for (int type : eSorted) {
+ for (int i = 0; i < getExtBombChoices()[type]; i++) {
+ int loc = availableBombLocation(BombType.bombCosts[type]);
+ if ((type == BombType.B_ALAMO)
+ && !game.getOptions().booleanOption(OptionsConstants.ADVAERORULES_AT2_NUKES)) {
+ continue;
+ }
+ if ((type > BombType.B_TAG)
+ && (gameTL < TechConstants.T_SIMPLE_ADVANCED)) {
+ continue;
+ }
+
+ // some bombs need an associated weapon and if so
+ // they need a weapon for each bomb
+ if (null != BombType.getBombWeaponName(type)) {
+ applyBombWeapons(type, loc, false);
+ } else {
+ applyBombEquipment(type, loc, false);
}
}
}
clearBombChoices();
}
+ /**
+ * Helper to apply equipment-type bombs, either externally or internally.
+ * @param type of bomb equipment.
+ * @param loc location where mounted.
+ * @param internal mounted internally or not.
+ */
+ private void applyBombEquipment(int type, int loc, boolean internal){
+ try {
+ EquipmentType et = EquipmentType.get(BombType.getBombInternalName(type));
+ Mounted m = ((Entity) this).addEquipment(et, loc, false);
+ m.setInternalBomb(internal);
+ } catch (LocationFullException ignored) {
+
+ }
+
+ }
+
+ /**
+ * Helper to apply weapon-type bombs, either externally or internally.
+ * @param type of bomb equipment.
+ * @param loc location where mounted.
+ * @param internal mounted internally or not.
+ */
+ private void applyBombWeapons(int type, int loc, boolean internal){
+ Mounted m;
+ try {
+ EquipmentType et = EquipmentType.get(BombType.getBombWeaponName(type));
+ m = ((Entity) this).addBomb(et, loc);
+ m.setInternalBomb(internal);
+ // Add bomb itself as single-shot ammo.
+ if (type != BombType.B_TAG) {
+ Mounted ammo = new Mounted((Entity) this,
+ EquipmentType.get(BombType.getBombInternalName(type)));
+ ammo.setShotsLeft(1);
+ ammo.setInternalBomb(internal);
+ m.setLinked(ammo);
+ ((Entity) this).addEquipment(ammo, loc, false);
+
+ }
+ } catch (LocationFullException ignored) {
+
+ }
+ }
+
void clearBombs();
+
+ /**
+ * @return maximum number of bomb points this bomber can mount externally
+ */
+ int getMaxExtBombPoints();
+
+ /**
+ * @return maximum number of bomb points this bomber can mount internally
+ */
+ int getMaxIntBombPoints();
}
diff --git a/megamek/src/megamek/common/LandAirMech.java b/megamek/src/megamek/common/LandAirMech.java
index 3954afcdb50..5ce443a2755 100644
--- a/megamek/src/megamek/common/LandAirMech.java
+++ b/megamek/src/megamek/common/LandAirMech.java
@@ -125,7 +125,11 @@ public String[] getLocationAbbrs() {
//Autoejection
private boolean critThresh = false;
- private int[] bombChoices = new int[BombType.B_NUM];
+ // Bomb choices
+
+ protected int[] intBombChoices = new int[BombType.B_NUM];
+ protected int[] extBombChoices = new int[BombType.B_NUM];
+
private Targetable airmechBombTarget = null;
private int fuel;
@@ -1083,31 +1087,68 @@ public int getWhoFirst() {
return whoFirst;
}
- @Override
public int getMaxBombPoints() {
+ return getMaxExtBombPoints() + getMaxIntBombPoints();
+ }
+
+ @Override
+ public int getMaxExtBombPoints() {
+ return 0;
+ }
+ @Override
+ public int getMaxIntBombPoints() {
return countWorkingMisc(MiscType.F_BOMB_BAY);
}
+ /**
+ *
+ * @return Largest empty bay size
+ */
@Override
- public int getMaxBombSize() {
+ public int getMaxIntBombSize() {
return Math.max(emptyBaysInLoc(LOC_CT), Math.max(emptyBaysInLoc(LOC_RT), emptyBaysInLoc(LOC_LT)));
}
@Override
- public int[] getBombChoices() {
- return bombChoices.clone();
+ public int[] getIntBombChoices() {
+ return intBombChoices.clone();
}
@Override
- public void setBombChoices(int[] bc) {
- if (bc.length == bombChoices.length) {
- bombChoices = bc;
+ public void setIntBombChoices(int[] bc) {
+ if (bc.length == intBombChoices.length) {
+ intBombChoices = bc.clone();
}
}
+ @Override
+ public void setUsedInternalBombs(int b){
+ // Do nothing; LAMs don't take internal bomb bay hits like this
+ }
+
+ @Override
+ public void increaseUsedInternalBombs(int b){
+ // Do nothing
+ }
+
+ @Override
+ public int getUsedInternalBombs() {
+ // Currently not possible
+ return 0;
+ }
+
+ @Override
+ public int[] getExtBombChoices() {
+ return extBombChoices;
+ }
+
+ @Override
+ public void setExtBombChoices(int[] bc) {
+ }
+
@Override
public void clearBombChoices() {
- Arrays.fill(bombChoices, 0);
+ Arrays.fill(intBombChoices, 0);
}
@Override
diff --git a/megamek/src/megamek/common/MULParser.java b/megamek/src/megamek/common/MULParser.java
index 37d5595d371..ac47142ca10 100644
--- a/megamek/src/megamek/common/MULParser.java
+++ b/megamek/src/megamek/common/MULParser.java
@@ -2250,17 +2250,29 @@ private void parseBombs(Element bombsTag, Entity entity) {
Element currEle = (Element) currNode;
String nodeName = currNode.getNodeName();
if (nodeName.equalsIgnoreCase(BOMB)) {
- int[] bombChoices = ((IBomber) entity).getBombChoices();
+ int[] intBombChoices = ((IBomber) entity).getIntBombChoices();
+ int[] extBombChoices = ((IBomber) entity).getExtBombChoices();
String type = currEle.getAttribute(TYPE);
String load = currEle.getAttribute(LOAD);
+ boolean internal = Boolean.parseBoolean(currEle.getAttribute(INTERNAL));
if (!type.isBlank() && !load.isBlank()) {
int bombType = BombType.getBombTypeFromInternalName(type);
if ((bombType <= BombType.B_NONE) || (bombType >= BombType.B_NUM)) {
continue;
}
- bombChoices[bombType] += Integer.parseInt(load);
- ((IBomber) entity).setBombChoices(bombChoices);
+ try {
+ if (internal) {
+ intBombChoices[bombType] += Integer.parseInt(load);
+ ((IBomber) entity).setIntBombChoices(intBombChoices);
+ } else {
+ extBombChoices[bombType] += Integer.parseInt(load);
+ ((IBomber) entity).setExtBombChoices(extBombChoices);
+ }
+ } catch (NumberFormatException ignore) {
+ // If something wrote bad bomb data, don't even bother with it - user
+ // can fix it in configure menu
+ }
}
}
}
diff --git a/megamek/src/megamek/common/MechFileParser.java b/megamek/src/megamek/common/MechFileParser.java
index 48631799441..5cae8f93f0a 100644
--- a/megamek/src/megamek/common/MechFileParser.java
+++ b/megamek/src/megamek/common/MechFileParser.java
@@ -123,7 +123,9 @@ public void parse(InputStream is, String fileName) throws Exception {
} else if (sType.equals("SupportVTOL")) {
loader = new BLKSupportVTOLFile(bb);
} else if (sType.equals("Aero")) {
- loader = new BLKAeroFile(bb);
+ loader = new BLKAeroSpaceFighterFile(bb);
+ } else if (sType.equals("AeroSpaceFighter")) {
+ loader = new BLKAeroSpaceFighterFile(bb);
} else if (sType.equals("FixedWingSupport")) {
loader = new BLKFixedWingSupportFile(bb);
} else if (sType.equals("ConvFighter")) {
@@ -191,7 +193,7 @@ public static void postLoadInit(Entity ent) throws EntityLoadingException {
// Conventional Fighters get a combined sensor suite
ent.getSensors().add(new Sensor(Sensor.TYPE_AERO_SENSOR));
ent.setNextSensor(ent.getSensors().firstElement());
- } else if (ent.hasETypeFlag(Entity.ETYPE_DROPSHIP)
+ } else if (ent.hasETypeFlag(Entity.ETYPE_DROPSHIP)
|| ent.hasETypeFlag(Entity.ETYPE_SPACE_STATION)
|| ent.hasETypeFlag(Entity.ETYPE_JUMPSHIP)
|| ent.hasETypeFlag(Entity.ETYPE_WARSHIP)) {
@@ -414,7 +416,7 @@ else if (m.getType().hasFlag(MiscType.F_APOLLO)
ent.setNextSensor(ent.getSensors().lastElement());
} else if (m.getType().getInternalName().equals(Sensor.BAPP)) {
ent.getSensors().add(new Sensor(Sensor.TYPE_BAPP));
- ent.setNextSensor(ent.getSensors().lastElement());
+ ent.setNextSensor(ent.getSensors().lastElement());
} else if (m.getType().getInternalName().equals(Sensor.BLOODHOUND)) {
ent.getSensors().add(new Sensor(Sensor.TYPE_BLOODHOUND));
ent.setNextSensor(ent.getSensors().lastElement());
@@ -568,7 +570,7 @@ else if (m.getType().hasFlag(MiscType.F_APOLLO)
|| (mWeapon.getType() instanceof ISSnubNosePPC)
|| (mWeapon.getType() instanceof CLEnhancedPPC)
|| (mWeapon.getType() instanceof CLImprovedPPC)
- || (mWeapon.getType() instanceof ISKinsSlaughterPPC)
+ || (mWeapon.getType() instanceof ISKinsSlaughterPPC)
|| (mWeapon.getType() instanceof CLERPPC && ent.getYear() >= 3101)) {
m.setCrossLinked(mWeapon);
@@ -751,7 +753,7 @@ else if ((ent instanceof Infantry) && ((Infantry) ent).canMakeAntiMekAttacks())
throw new EntityLoadingException(ex.getMessage());
}
}
-
+
// Check if it's canon; if it is, mark it as such.
ent.setCanon(false);// Guilty until proven innocent
try {
@@ -782,7 +784,7 @@ else if ((ent instanceof Infantry) && ((Infantry) ent).canMakeAntiMekAttacks())
int index = Collections.binarySearch(canonUnitNames, ent.getShortNameRaw());
if (index >= 0) {
ent.setCanon(true);
- }
+ }
ent.initMilitary();
linkDumpers(ent);
}
diff --git a/megamek/src/megamek/common/MechSearchFilter.java b/megamek/src/megamek/common/MechSearchFilter.java
index 3dfa3d79a0f..8f9b8325578 100644
--- a/megamek/src/megamek/common/MechSearchFilter.java
+++ b/megamek/src/megamek/common/MechSearchFilter.java
@@ -787,10 +787,6 @@ public static boolean isMatch(MechSummary mech, MechSearchFilter f) {
long entityType = mech.getEntityType();
- if (mech.isAerospaceFighter()) {
- entityType = entityType | Entity.ETYPE_AEROSPACEFIGHTER;
- }
-
long entityTypes = 0;
if (f.filterMech == 1) {
@@ -1037,10 +1033,10 @@ private boolean evaluate(List eq, List qty, ExpNode n) {
} else if (currEq.equals(n.name) && n.qty == 0) {
return false;
}
-
+
}
- // If we reach this point. It means that the MechSummary didn't have a weapon/equipment that matched the leaf node.
+ // If we reach this point. It means that the MechSummary didn't have a weapon/equipment that matched the leaf node.
// If the leaf quantity is 0, that means that the mech is a match. If the leaf quantity is non-zero, that means the mech isn't
// a match.
if (n.qty == 0) {
diff --git a/megamek/src/megamek/common/MechSummary.java b/megamek/src/megamek/common/MechSummary.java
index 24e797accd5..6818559a7f5 100644
--- a/megamek/src/megamek/common/MechSummary.java
+++ b/megamek/src/megamek/common/MechSummary.java
@@ -129,16 +129,16 @@ public class MechSummary implements Serializable, ASCardDisplayable {
/** The type of internal structure on this unit **/
private int internalsType;
-
+
/**
* Each location can have a separate armor type, but this is used for search purposes. We really
* only care about which types are present.
*/
private final HashSet armorTypeSet;
-
+
/** The armor type for each location. */
private int[] armorLoc;
-
+
/** The armor tech type for each location. */
private int[] armorLocTech;
@@ -257,15 +257,17 @@ public static String determineETypeName(MechSummary ms) {
case "Jumpship":
case "Dropship":
case "Small Craft":
- case "Conventional Fighter":
case "Aero":
return Entity.getEntityMajorTypeName(Entity.ETYPE_AERO);
+ case "Conventional Fighter":
+ case "AeroSpaceFighter":
+ return Entity.getEntityMajorTypeName(Entity.ETYPE_AEROSPACEFIGHTER);
case "Unknown":
return Entity.getEntityMajorTypeName(-1);
}
return Entity.getEntityMajorTypeName(-1);
}
-
+
// This is here for legacy purposes to not break the API
@Deprecated
public static String determineUnitType(Entity e) {
@@ -307,11 +309,11 @@ public int getYear() {
public int getType() {
return type;
}
-
+
public int[] getAltTypes() {
return altTypes;
}
-
+
public int getType(int year) {
if (year >= stdTechYear) {
return altTypes[0];
@@ -529,7 +531,7 @@ public long getModified() {
public String getLevel() {
return level;
}
-
+
public int getAdvancedTechYear() {
return advTechYear;
}
@@ -537,7 +539,7 @@ public int getAdvancedTechYear() {
public int getStandardTechYear() {
return stdTechYear;
}
-
+
public String getLevel(int year) {
if (level.equals("F")) {
return level;
@@ -871,11 +873,11 @@ public void setYear(int nYear) {
public void setType(int nType) {
this.type = nType;
}
-
+
public void setAltTypes(int[] altTypes) {
this.altTypes = altTypes;
}
-
+
public void setTons(double nTons) {
this.tons = nTons;
}
@@ -911,11 +913,11 @@ public void setModified(long lModified) {
public void setLevel(String level) {
this.level = level;
}
-
+
public void setAdvancedYear(int year) {
advTechYear = year;
}
-
+
public void setStandardYear(int year) {
stdTechYear = year;
}
@@ -996,11 +998,11 @@ public int getJumpMp() {
public void setJumpMp(int jumpMp) {
this.jumpMp = jumpMp;
}
-
+
/**
* Given the list of equipment mounted on this unit, parse it into a unique
* list of names and the number of times that name appears.
- *
+ *
* @param mountedList A collection of Mounted
equipment
*/
public void setEquipment(List mountedList)
@@ -1020,14 +1022,14 @@ public void setEquipment(List mountedList)
equipmentQuantities.add(1);
} else { // We've seen this before, update count
equipmentQuantities.set(index, equipmentQuantities.get(index)+1);
- }
+ }
}
}
-
+
public Vector getEquipmentNames() {
return equipmentNames;
}
-
+
public Vector getEquipmentQuantities() {
return equipmentQuantities;
}
@@ -1084,9 +1086,9 @@ public int getInternalsType() {
}
/**
- * Takes the armor type at all locations and creates a set of the armor
+ * Takes the armor type at all locations and creates a set of the armor
* types.
- *
+ *
* @param locsArmor An array that stores the armor type at each location.
*/
public void setArmorType(int[] locsArmor) {
@@ -1099,19 +1101,19 @@ public void setArmorType(int[] locsArmor) {
public HashSet getArmorType() {
return armorTypeSet;
}
-
+
public int[] getArmorTypes() {
return armorLoc;
}
-
+
public void setArmorTypes(int[] al) {
armorLoc = al;
}
-
+
public int[] getArmorTechTypes() {
return armorLocTech;
}
-
+
public void setArmorTechTypes(int[] att) {
armorLocTech = att;
}
@@ -1249,7 +1251,7 @@ public boolean equals(Object obj) {
return Objects.equals(chassis, other.chassis) && Objects.equals(model, other.model)
&& Objects.equals(unitType, other.unitType) && Objects.equals(sourceFile, other.sourceFile);
}
-
+
@Override
public int hashCode() {
return Objects.hash(chassis, model, unitType, sourceFile);
diff --git a/megamek/src/megamek/common/MechView.java b/megamek/src/megamek/common/MechView.java
index 71e20165469..da062e0f5c0 100644
--- a/megamek/src/megamek/common/MechView.java
+++ b/megamek/src/megamek/common/MechView.java
@@ -33,18 +33,18 @@
/**
* A utility class for retrieving unit information in a formatted string.
- *
+ *
* The information is encoded in a series of classes that implement a common {@link ViewElement}
* interface, which can format the element either in html or in plain text.
* @author Ryan McConnell
* @since January 20, 2003
*/
public class MechView {
-
+
/**
* Provides common interface for various ways to present data that can be formatted
* either as HTML or as plain text.
- *
+ *
* @see SingleLine
* @see LabeledElement
* @see TableElement
@@ -78,24 +78,24 @@ interface ViewElement {
private List sBasic = new ArrayList<>();
private List sLoadout = new ArrayList<>();
private List sFluff = new ArrayList<>();
-
+
private final boolean html;
/**
* Compiles information about an {@link Entity} useful for showing a summary of its abilities.
* Produced output formatted in html.
- *
+ *
* @param entity The entity to summarize
* @param showDetail If true, shows individual weapons that make up weapon bays.
*/
public MechView(Entity entity, boolean showDetail) {
this(entity, showDetail, false, true);
}
-
+
/**
* Compiles information about an {@link Entity} useful for showing a summary of its abilities.
* Produced output formatted in html.
- *
+ *
* @param entity The entity to summarize
* @param showDetail If true, shows individual weapons that make up weapon bays.
* @param useAlternateCost If true, uses alternate cost calculation. This primarily provides an
@@ -122,7 +122,7 @@ public MechView(final Entity entity, final boolean showDetail, final boolean use
/**
* Compiles information about an {@link Entity} useful for showing a summary of its abilities.
- *
+ *
* @param entity The entity to summarize
* @param showDetail If true, shows individual weapons that make up weapon bays.
* @param useAlternateCost If true, uses alternate cost calculation. This primarily provides an
@@ -192,7 +192,7 @@ public MechView(final Entity entity, final boolean showDetail, final boolean use
}
sLoadout.add(specList);
}
-
+
if (inf.getCrew() != null) {
ArrayList augmentations = new ArrayList<>();
for (Enumeration e = inf.getCrew().getOptions(PilotOptions.MD_ADVANTAGES);
@@ -232,7 +232,7 @@ public MechView(final Entity entity, final boolean showDetail, final boolean use
if (!entity.isDesignValid()) {
sHead.add(new SingleLine(Messages.getString("MechView.DesignInvalid")));
}
-
+
TableElement tpTable = new TableElement(3);
String tableSpacer = " ";
tpTable.setColNames(Messages.getString("MechView.Level"), tableSpacer,
@@ -259,7 +259,7 @@ public MechView(final Entity entity, final boolean showDetail, final boolean use
tpTable.addRow(Messages.getString("MechView.Extinct"), tableSpacer, extinctRange);
}
sHead.add(tpTable);
-
+
sHead.add(new LabeledElement(Messages.getString("MechView.TechRating"), entity.getFullRatingName()));
sHead.add(new SingleLine());
@@ -416,7 +416,7 @@ public MechView(final Entity entity, final boolean showDetail, final boolean use
.append(" damaged)").append(warningEnd());
}
sBasic.add(new LabeledElement(Messages.getString("MechView.HeatSinks"), hsString.toString()));
-
+
sBasic.add(new LabeledElement(Messages.getString("MechView.Cockpit"),
a.getCockpitTypeString()));
}
@@ -455,7 +455,7 @@ public MechView(final Entity entity, final boolean showDetail, final boolean use
sBasic.add(new LabeledElement(Messages.getString("MechView.SystemDamage"),
warningStart() + a.getCritDamageString() + warningEnd()));
}
-
+
String fuel = String.valueOf(a.getCurrentFuel());
if (a.getCurrentFuel() < a.getFuel()) {
fuel += "/" + a.getFuel();
@@ -546,10 +546,10 @@ private String eraText(int startYear, int endYear) {
}
return eraText;
}
-
+
/**
* Converts a list of {@link ViewElement}s to a String using the selected format.
- *
+ *
* @param section The elements to format.
* @return The formatted data.
*/
@@ -558,7 +558,7 @@ private String getReadout(List section) {
ViewElement::toHTML : ViewElement::toPlainText;
return section.stream().map(mapper).collect(Collectors.joining());
}
-
+
/**
* The head section includes the title (unit name), tech level and availability, tonnage, bv, and cost.
* @return The data from the head section.
@@ -592,9 +592,9 @@ public String getMechReadoutLoadout() {
public String getMechReadoutFluff() {
return getReadout(sFluff);
}
-
+
/**
- * @return A summary including all four sections.
+ * @return A summary including all four sections.
*/
public String getMechReadout() {
return getMechReadout(null);
@@ -617,7 +617,7 @@ public String getMechReadout(@Nullable String fontName) {
private List getInternalAndArmor() {
List retVal = new ArrayList<>();
-
+
int maxArmor = (entity.getTotalInternal() * 2) + 3;
if (isInf && !isBA) {
Infantry inf = (Infantry) entity;
@@ -685,7 +685,7 @@ private List getInternalAndArmor() {
String[] row = {entity.getLocationName(loc),
renderArmor(entity.getInternalForReal(loc), entity.getOInternal(loc), html),
"", "", "" };
-
+
if (IArmorState.ARMOR_NA != entity.getArmorForReal(loc)) {
row[2] = renderArmor(entity.getArmorForReal(loc),
entity.getOArmor(loc), html);
@@ -831,7 +831,7 @@ private List getWeapons(boolean showDetail) {
if (entity.getWeaponList().isEmpty()) {
return retVal;
}
-
+
TableElement wpnTable = new TableElement(4);
wpnTable.setColNames("Weapons ", " Loc ", " Heat ", entity.isOmni() ? " Omni " : "");
wpnTable.setJustification(TableElement.JUSTIFIED_LEFT, TableElement.JUSTIFIED_CENTER,
@@ -873,7 +873,7 @@ private List getWeapons(boolean showDetail) {
}
}
row[2] = String.valueOf(heat);
-
+
if (entity.isOmni()) {
row[3] = Messages.getString(mounted.isOmniPodMounted() ? "MechView.Pod" : "MechView.Fixed");
} else if (wtype instanceof BayWeapon && bWeapDamaged > 0 && !showDetail) {
@@ -890,16 +890,16 @@ private List getWeapons(boolean showDetail) {
wpnTable.addRow(row);
}
- // if this is a weapon bay, then cycle through weapons and ammo
+ // if this is a weapon bay, then cycle through weapons and ammo
if ((wtype instanceof BayWeapon) && showDetail) {
- for (int wId : mounted.getBayWeapons()) {
+ for (int wId : mounted.getBayWeapons()) {
Mounted m = entity.getEquipment(wId);
- if (null == m) {
- continue;
+ if (null == m) {
+ continue;
}
-
+
row = new String[] { m.getDesc(), "", "", "" };
-
+
if (entity.isClan()
&& (mounted.getType().getTechBase() == ITechnology.TECH_BASE_IS)) {
row[0] += Messages.getString("MechView.IS");
@@ -920,8 +920,8 @@ private List getWeapons(boolean showDetail) {
}
for (int aId : mounted.getBayAmmo()) {
Mounted m = entity.getEquipment(aId);
- if (null == m) {
- continue;
+ if (null == m) {
+ continue;
}
// Ignore ammo for one-shot launchers
if ((m.getLinkedBy() != null)
@@ -965,7 +965,7 @@ private ViewElement getAmmo() {
if (mounted.getSize() == 0) {
continue;
}
-
+
if (mounted.getLocation() == Entity.LOC_NONE) {
continue;
}
@@ -1014,7 +1014,13 @@ private ViewElement getAmmo() {
private List getBombs() {
List retVal = new ArrayList<>();
IBomber b = (IBomber) entity;
- int[] choices = b.getBombChoices();
+ int[] choices = b.getIntBombChoices();
+ for (int type = 0; type < BombType.B_NUM; type++) {
+ if (choices[type] > 0) {
+ retVal.add(new SingleLine(BombType.getBombName(type) + " (" + choices[type] + ") [Int. Bay]"));
+ }
+ }
+ choices = b.getExtBombChoices();
for (int type = 0; type < BombType.B_NUM; type++) {
if (choices[type] > 0) {
retVal.add(new SingleLine(BombType.getBombName(type) + " (" + choices[type] + ")"));
@@ -1025,7 +1031,7 @@ private List getBombs() {
private List getMisc() {
List retVal = new ArrayList<>();
-
+
TableElement miscTable = new TableElement(3);
miscTable.setColNames("Equipment", "Loc", entity.isOmni() ? "Omni" : "");
miscTable.setJustification(TableElement.JUSTIFIED_LEFT, TableElement.JUSTIFIED_CENTER,
@@ -1040,7 +1046,7 @@ private List getMisc() {
|| (name.contains("CASE")
&& !name.contains("II")
&& entity.isClan())
- || (name.contains("Heat Sink")
+ || (name.contains("Heat Sink")
&& !name.contains("Radical"))
|| EquipmentType.isArmorType(mounted.getType())
|| EquipmentType.isStructureType(mounted.getType())) {
@@ -1048,7 +1054,7 @@ private List getMisc() {
continue;
}
nEquip++;
-
+
String[] row = { mounted.getDesc(), entity.joinLocationAbbr(mounted.allLocations(), 3), "" };
if (entity.isClan()
&& (mounted.getType().getTechBase() == ITechnology.TECH_BASE_IS)) {
@@ -1058,7 +1064,7 @@ private List getMisc() {
&& (mounted.getType().getTechBase() == ITechnology.TECH_BASE_CLAN)) {
row[0] += Messages.getString("MechView.Clan");
}
-
+
if (entity.isOmni()) {
row[2] = Messages.getString(mounted.isOmniPodMounted() ? "MechView.Pod" : "MechView.Fixed");
}
@@ -1168,9 +1174,9 @@ public String toPlainText() {
public String toHTML() {
return "";
}
-
+
}
-
+
/**
* Basic one-line entry consisting of a label, a colon, and a value. In html the label is bold.
*
@@ -1178,12 +1184,12 @@ public String toHTML() {
private static class LabeledElement implements ViewElement {
private final String label;
private final String value;
-
+
LabeledElement(String label, String value) {
this.label = label;
this.value = value;
}
-
+
@Override
public String toPlainText() {
String htmlCleanedText = value.replaceAll("<[Bb][Rr]> *", "\n")
@@ -1192,13 +1198,13 @@ public String toPlainText() {
.replaceAll("<[^>]*>", "");
return label + ": " + htmlCleanedText + "\n";
}
-
+
@Override
public String toHTML() {
return "" + label + ": " + value + "
";
}
}
-
+
/**
* Data laid out in a table with named columns. The columns are left-justified by default,
* but justification can be set for columns individually. Plain text output requires a monospace
@@ -1206,23 +1212,23 @@ public String toHTML() {
*
*/
private static class TableElement implements ViewElement {
-
+
static final int JUSTIFIED_LEFT = 0;
static final int JUSTIFIED_CENTER = 1;
static final int JUSTIFIED_RIGHT = 2;
-
+
private final int[] justification;
private final String[] colNames;
private final List data = new ArrayList<>();
private final Map colWidth = new HashMap<>();
private final Map colors = new HashMap<>();
-
+
TableElement(int colCount) {
justification = new int[colCount];
colNames = new String[colCount];
Arrays.fill(colNames, "");
}
-
+
void setColNames(String... colNames) {
Arrays.fill(this.colNames, "");
System.arraycopy(colNames, 0, this.colNames, 0,
@@ -1232,25 +1238,25 @@ void setColNames(String... colNames) {
colWidth.put(i, colNames[i].length());
}
}
-
+
void setJustification(int... justification) {
Arrays.fill(this.justification, JUSTIFIED_LEFT);
System.arraycopy(justification, 0, this.justification, 0,
Math.min(justification.length, this.justification.length));
}
-
+
void addRow(String... row) {
data.add(row);
for (int i = 0; i < row.length; i++) {
colWidth.merge(i, row[i].length(), Math::max);
}
}
-
+
void addRowWithColor(String color, String... row) {
addRow(row);
colors.put(data.size() - 1, color);
}
-
+
private String leftPad(String s, int fieldSize) {
if (fieldSize > 0) {
return String.format("%" + fieldSize + "s", s);
@@ -1258,7 +1264,7 @@ private String leftPad(String s, int fieldSize) {
return "";
}
}
-
+
private String rightPad(String s, int fieldSize) {
if (fieldSize > 0) {
return String.format("%-" + fieldSize + "s", s);
@@ -1266,12 +1272,12 @@ private String rightPad(String s, int fieldSize) {
return "";
}
}
-
+
private String center(String s, int fieldSize) {
int rightPadding = Math.max(fieldSize - s.length(), 0) / 2;
return rightPad(leftPad(s, fieldSize - rightPadding), fieldSize);
}
-
+
private String justify(int justification, String s, int fieldSize) {
if (justification == JUSTIFIED_CENTER) {
return center(s, fieldSize);
@@ -1281,7 +1287,7 @@ private String justify(int justification, String s, int fieldSize) {
return leftPad(s, fieldSize);
}
}
-
+
@Override
public String toPlainText() {
final String COL_PADDING = " ";
@@ -1309,7 +1315,7 @@ public String toPlainText() {
}
return sb.toString();
}
-
+
@Override
public String toHTML() {
StringBuilder sb = new StringBuilder("");
@@ -1364,7 +1370,7 @@ public String toHTML() {
return sb.toString();
}
}
-
+
/**
* Displays a label (bold for html output) followed by a column of items
*
@@ -1372,15 +1378,15 @@ public String toHTML() {
private static class ItemList implements ViewElement {
private final String heading;
private final List data = new ArrayList<>();
-
+
ItemList(String heading) {
this.heading = heading;
}
-
+
void addItem(String item) {
data.add(item);
}
-
+
@Override
public String toPlainText() {
StringBuilder sb = new StringBuilder();
@@ -1394,7 +1400,7 @@ public String toPlainText() {
}
return sb.toString();
}
-
+
@Override
public String toHTML() {
StringBuilder sb = new StringBuilder();
@@ -1407,27 +1413,27 @@ public String toHTML() {
return sb.toString();
}
}
-
+
/**
* Displays a single line of text. The default constructor is used to insert a new line.
*/
private static class SingleLine implements ViewElement {
-
+
private final String value;
-
+
SingleLine(String value) {
this.value = value;
}
-
+
SingleLine() {
this("");
}
-
+
@Override
public String toPlainText() {
return value + "\n";
}
-
+
@Override
public String toHTML() {
return value + "
\n";
@@ -1467,29 +1473,29 @@ public String toHTML() {
return result + "" + displayText + "
";
}
}
-
+
/**
* Displays a single line in bold in a larger font in html. In plain text simply displays a single line.
*/
private static class Title implements ViewElement {
-
+
private final String title;
-
+
Title(String title) {
this.title = title;
}
-
+
@Override
public String toPlainText() {
return title + "\n";
}
-
+
@Override
public String toHTML() {
return "" + title + "
\n";
}
}
-
+
/**
* Marks warning text; in html the text is displayed in red. In plain text it is preceded and followed
* by an asterisk.
@@ -1502,7 +1508,7 @@ private String warningStart() {
return "*";
}
}
-
+
/**
* Returns the end element of the warning text.
* @return A String that is used to mark the end of a warning.
@@ -1514,7 +1520,7 @@ private String warningEnd() {
return "*";
}
}
-
+
/**
* Marks the beginning of a section of italicized text if using html output. For plain text
* returns an empty String.
@@ -1527,7 +1533,7 @@ private String italicsStart() {
return "";
}
}
-
+
/**
* Marks the end of a section of italicized text.
* @return The ending element for italicized text.
diff --git a/megamek/src/megamek/common/Mounted.java b/megamek/src/megamek/common/Mounted.java
index fe9076d7c6b..c91a4a19b75 100644
--- a/megamek/src/megamek/common/Mounted.java
+++ b/megamek/src/megamek/common/Mounted.java
@@ -110,6 +110,7 @@ public class Mounted implements Serializable, RoundUpdated, PhaseUpdated {
// bomb stuff
private boolean bombMounted = false;
+ private boolean isInternalBomb = false;
// mine type
private int mineType = MINE_NONE;
@@ -550,6 +551,10 @@ public String getDesc() {
if (isArmored()) {
desc.append(" (armored)");
}
+
+ if (isInternalBomb()) {
+ desc.append(" (Int. Bay)");
+ }
return desc.toString();
}
@@ -1631,6 +1636,19 @@ public boolean isGroundBomb() {
getType().hasFlag(AmmoType.F_GROUND_BOMB);
}
+ public void setInternalBomb(boolean internal) {
+ isInternalBomb = internal;
+ }
+
+ /**
+ * Convenience method to determine if a bomb munition is mounted EXternally (reduces MP) or INternally (no
+ * MP reduction).
+ * @return True if
+ */
+ public boolean isInternalBomb() {
+ return isInternalBomb;
+ }
+
// is ammo in the same bay as the weapon
public boolean ammoInBay(int mAmmoId) {
for (int nextAmmoId : bayAmmo) {
diff --git a/megamek/src/megamek/common/SmallCraft.java b/megamek/src/megamek/common/SmallCraft.java
index fb6be7bd94a..ef7a811b951 100644
--- a/megamek/src/megamek/common/SmallCraft.java
+++ b/megamek/src/megamek/common/SmallCraft.java
@@ -25,35 +25,35 @@
public class SmallCraft extends Aero {
private static final long serialVersionUID = 6708788176436555036L;
-
+
public static final int LOC_HULL = 4;
-
- private static String[] LOCATION_ABBRS = { "NOS", "LS", "RS", "AFT", "HULL" };
- private static String[] LOCATION_NAMES = { "Nose", "Left Side", "Right Side", "Aft", "Hull" };
+
+ private static String[] LOCATION_ABBRS = {"NOS", "LS", "RS", "AFT", "HULL"};
+ private static String[] LOCATION_NAMES = {"Nose", "Left Side", "Right Side", "Aft", "Hull"};
// crew and passengers
private int nOfficers = 0;
private int nGunners = 0;
private int nBattleArmor = 0;
private int nOtherPassenger = 0;
-
+
// Maps transported crew, passengers, marines to a host ship so we can match them up again post-game
- private Map nOtherCrew = new HashMap<>();
- private Map passengers = new HashMap<>();
-
+ private Map nOtherCrew = new HashMap<>();
+ private Map passengers = new HashMap<>();
+
// escape pods and lifeboats
private int escapePods = 0;
private int lifeBoats = 0;
private int escapePodsLaunched = 0;
private int lifeBoatsLaunched = 0;
-
+
private static final TechAdvancement TA_SM_CRAFT = new TechAdvancement(TECH_BASE_ALL)
.setAdvancement(DATE_NONE, 2350, 2400).setISApproximate(false, true, false)
.setProductionFactions(F_TH).setTechRating(RATING_D)
.setAvailability(RATING_D, RATING_E, RATING_D, RATING_D)
.setStaticTechLevel(SimpleTechLevel.STANDARD);
private static final TechAdvancement TA_SM_CRAFT_PRIMITIVE = new TechAdvancement(TECH_BASE_IS)
- //Per MUL team and per availability codes should exist to around 2781
+ //Per MUL team and per availability codes should exist to around 2781
.setISAdvancement(DATE_ES, 2200, DATE_NONE, 2781, DATE_NONE)
.setISApproximate(false, true, false, true, false)
.setProductionFactions(F_TA).setTechRating(RATING_D)
@@ -73,7 +73,7 @@ public TechAdvancement getConstructionTechAdvancement() {
return TA_SM_CRAFT;
}
}
-
+
/**
* @return Returns the autoEject setting (always off for large craft)
*/
@@ -81,7 +81,7 @@ public TechAdvancement getConstructionTechAdvancement() {
public boolean isAutoEject() {
return false;
}
-
+
@Override
public boolean isPrimitive() {
return getArmorType(LOC_NOSE) == EquipmentType.T_ARMOR_PRIMITIVE_AERO;
@@ -96,15 +96,15 @@ public boolean isSmallCraft() {
public void setNCrew(int crew) {
nCrew = crew;
}
-
+
public void setNOfficers(int officer) {
nOfficers = officer;
}
-
+
public void setNGunners(int gunners) {
nGunners = gunners;
}
-
+
@Override
public void setNPassenger(int pass) {
nPassenger = pass;
@@ -132,17 +132,17 @@ public int getNCrew() {
public int getNPassenger() {
return nPassenger;
}
-
+
@Override
public int getNOfficers() {
return nOfficers;
}
-
+
@Override
public int getNGunners() {
return nGunners;
}
-
+
@Override
public int getNBattleArmor() {
return nBattleArmor;
@@ -156,15 +156,15 @@ public int getNMarines() {
public int getNOtherPassenger() {
return nOtherPassenger;
}
-
+
/**
* Returns a mapping of how many crewmembers from other units this unit is carrying
- * and what ship they're from by external ID
+ * and what ship they're from by external ID
*/
- public Map getNOtherCrew() {
+ public Map getNOtherCrew() {
return nOtherCrew;
}
-
+
/**
* Convenience method to return all crew from other craft aboard from the above Map
* @return
@@ -176,28 +176,28 @@ public int getTotalOtherCrew() {
}
return toReturn;
}
-
+
/**
* Adds a number of crewmembers from another ship keyed by that ship's external ID
* @param id The external ID of the ship these crew came from
* @param n The number to add
*/
public void addNOtherCrew(String id, int n) {
- if (nOtherCrew.containsKey(id)) {
- nOtherCrew.replace(id, nOtherCrew.get(id) + n);
- } else {
- nOtherCrew.put(id, n);
- }
+ if (nOtherCrew.containsKey(id)) {
+ nOtherCrew.replace(id, nOtherCrew.get(id) + n);
+ } else {
+ nOtherCrew.put(id, n);
+ }
}
-
+
/**
* Returns a mapping of how many passengers from other units this unit is carrying
- * and what ship they're from by external ID
+ * and what ship they're from by external ID
*/
- public Map getPassengers() {
+ public Map getPassengers() {
return passengers;
}
-
+
/**
* Convenience method to return all passengers aboard from the above Map
* @return
@@ -209,20 +209,20 @@ public int getTotalPassengers() {
}
return toReturn;
}
-
+
/**
* Adds a number of passengers from another ship keyed by that ship's external ID
* @param id The external ID of the ship these passengers came from
* @param n The number to add
*/
public void addPassengers(String id, int n) {
- if (passengers.containsKey(id)) {
- passengers.replace(id, passengers.get(id) + n);
- } else {
- passengers.put(id, n);
- }
+ if (passengers.containsKey(id)) {
+ passengers.replace(id, passengers.get(id) + n);
+ } else {
+ passengers.put(id, n);
+ }
}
-
+
public void setEscapePods(int n) {
escapePods = n;
}
@@ -231,7 +231,7 @@ public void setEscapePods(int n) {
public int getEscapePods() {
return escapePods;
}
-
+
/**
* Returns the total number of escape pods launched so far
*/
@@ -239,7 +239,7 @@ public int getEscapePods() {
public int getLaunchedEscapePods() {
return escapePodsLaunched;
}
-
+
/**
* Updates the total number of escape pods launched so far
* @param n The number to change
@@ -257,7 +257,7 @@ public void setLifeBoats(int n) {
public int getLifeBoats() {
return lifeBoats;
}
-
+
/**
* Returns the total number of lifeboats launched so far
*/
@@ -265,7 +265,7 @@ public int getLifeBoats() {
public int getLaunchedLifeBoats() {
return lifeBoatsLaunched;
}
-
+
/**
* Updates the total number of lifeboats launched so far
* @param n The number to change
@@ -274,7 +274,7 @@ public int getLaunchedLifeBoats() {
public void setLaunchedLifeBoats(int n) {
lifeBoatsLaunched = n;
}
-
+
@Override
public double getStrategicFuelUse() {
if (isPrimitive()) {
@@ -336,7 +336,7 @@ public HitData rollHitLocation(int table, int side) {
// special rules for spheroids in atmosphere
// http://www.classicbattletech.com/forums/index.php/topic,54077.0.html
- if (isSpheroid() && table != ToHitData.HIT_SPHEROID_CRASH &&
+ if (isSpheroid() && table != ToHitData.HIT_SPHEROID_CRASH &&
!game.getBoard().inSpace()) {
int preroll = Compute.d6(1);
if ((table == ToHitData.HIT_ABOVE) && (preroll < 4)) {
@@ -729,7 +729,7 @@ public double getArmorWeight() {
return RoundWeight.nextHalfTon(armorPoints / armorPerTon);
}
-
+
public static double armorPointsPerTon(double craftWeight, boolean spheroid, int at, boolean isClan) {
double base = 16.0;
if (spheroid) {
@@ -891,12 +891,23 @@ public int height() {
public long getEntityType() {
return Entity.ETYPE_AERO | Entity.ETYPE_SMALL_CRAFT;
}
-
+
@Override
public boolean isFighter() {
return false;
}
+ /**
+ * Fighters may carry external ordnance;
+ * Other Aerospace units with cargo bays and the Internal Bomb Bay quirk may carry bombs internally.
+ * @return boolean
+ */
+ @Override
+ public boolean isBomber() {
+ return (hasQuirk(OptionsConstants.QUIRK_POS_INTERNAL_BOMB));
+ }
+
+
@Override
public boolean isAerospaceFighter() {
return false;
@@ -919,4 +930,12 @@ public boolean isLargeAerospace() {
public int getLandingLength() {
return 8;
}
+
+ @Override
+ public void autoSetMaxBombPoints() {
+ // Only internal cargo bays can be considered for this type of unit.
+ maxIntBombPoints = getTransportBays().stream().mapToInt(
+ tb -> (tb instanceof CargoBay) ? (int) Math.floor(tb.getUnused()) : 0
+ ).sum();
+ }
}
\ No newline at end of file
diff --git a/megamek/src/megamek/common/UnitType.java b/megamek/src/megamek/common/UnitType.java
index 6eebef72d07..bfb064f7244 100644
--- a/megamek/src/megamek/common/UnitType.java
+++ b/megamek/src/megamek/common/UnitType.java
@@ -28,17 +28,18 @@ public class UnitType {
public static final int NAVAL = 6;
public static final int GUN_EMPLACEMENT = 7;
public static final int CONV_FIGHTER = 8;
- public static final int AERO = 9;
+ public static final int AEROSPACEFIGHTER = 9;
public static final int SMALL_CRAFT = 10;
public static final int DROPSHIP = 11;
public static final int JUMPSHIP = 12;
public static final int WARSHIP = 13;
public static final int SPACE_STATION = 14;
+ public static final int AERO = 15; // Non-differentiated Aerospace, like Escape Pods / Life Boats
private static String[] names = { "Mek", "Tank", "BattleArmor", "Infantry",
"ProtoMek", "VTOL", "Naval", "Gun Emplacement", "Conventional Fighter",
- "Aero", "Small Craft", "Dropship",
- "Jumpship", "Warship", "Space Station" };
+ "AeroSpaceFighter", "Small Craft", "Dropship",
+ "Jumpship", "Warship", "Space Station", "Aero"};
public static final int SIZE = names.length;
@@ -50,7 +51,7 @@ public static String determineUnitType(Entity e) {
/**
* Reverse lookup for type integer constant from name
- *
+ *
* @param name Unit type name
* @return The unit type constant. If no match can be found, returns -1.
*/
@@ -82,9 +83,9 @@ public static String getTypeDisplayableName(int type) {
}
throw new IllegalArgumentException("Unknown unit type");
}
-
+
// series of convenience methods to shorten unit type determination
-
+
/**
* Whether the given entity is a VTOL
* @param e the entity to examine
@@ -93,7 +94,7 @@ public static String getTypeDisplayableName(int type) {
public static boolean isVTOL(Entity e) {
return e.getEntityType() == Entity.ETYPE_VTOL;
}
-
+
/**
* Whether the given entity is a Spheroid dropship
* @param e the entity to examine
diff --git a/megamek/src/megamek/common/VTOL.java b/megamek/src/megamek/common/VTOL.java
index 9cf3106d2b9..f422afa1368 100644
--- a/megamek/src/megamek/common/VTOL.java
+++ b/megamek/src/megamek/common/VTOL.java
@@ -52,8 +52,8 @@ public VTOL() {
// need to set elevation to something different than entity
elevation = 1;
}
-
-
+
+
@Override
public int getUnitType() {
return UnitType.VTOL;
@@ -73,13 +73,15 @@ public String[] getLocationNames() {
public int getLocTurret() {
return LOC_TURRET;
}
-
+
@Override
public int getLocTurret2() {
return LOC_TURRET_2;
}
- private int[] bombChoices = new int[BombType.B_NUM];
+ protected int[] intBombChoices = new int[BombType.B_NUM];
+ protected int[] extBombChoices = new int[BombType.B_NUM];
+
private Targetable bombTarget = null;
private List strafingCoords = new ArrayList<>();
@@ -240,38 +242,57 @@ public boolean doomedInVacuum() {
public boolean doomedInAtmosphere() {
return true;
}
-
+
@Override
public boolean isBomber() {
return (game != null)
- && game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_VTOL_ATTACKS);
+ && (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_VTOL_ATTACKS));
}
-
+
@Override
public int availableBombLocation(int cost) {
return LOC_FRONT;
}
-
+
@Override
- public int getMaxBombPoints() {
+ public int getMaxExtBombPoints() {
return (int) Math.round(getWeight() / 5);
}
+ @Override
+ public int getMaxIntBombPoints() {
+ return 0;
+ }
+
+
+ @Override
+ public int getMaxBombPoints() {
+ return getMaxExtBombPoints();
+ }
+
+ @Override
+ public int[] getIntBombChoices() {
+ return intBombChoices.clone();
+ }
@Override
- public int[] getBombChoices() {
- return bombChoices.clone();
+ public void setIntBombChoices(int[] bc) {
}
@Override
- public void setBombChoices(int... bc) {
- if (bc.length == bombChoices.length) {
- bombChoices = bc;
+ public int[] getExtBombChoices() {
+ return extBombChoices.clone();
+ }
+
+ @Override
+ public void setExtBombChoices(int[] bc) {
+ if (bc.length == extBombChoices.length) {
+ extBombChoices = bc;
}
}
-
+
@Override
public void clearBombChoices() {
- Arrays.fill(bombChoices, 0);
+ Arrays.fill(extBombChoices, 0);
}
@Override
@@ -280,16 +301,32 @@ public int reduceMPByBombLoad(int t) {
return Math.max(0, (t - (int) this.getBombs().stream().filter(m -> (m.getUsableShotsLeft() > 0)).count()));
}
+ @Override
+ public void setUsedInternalBombs(int b){
+ // Do nothing
+ }
+
+ @Override
+ public void increaseUsedInternalBombs(int b){
+ // Do nothing
+ }
+
+ @Override
+ public int getUsedInternalBombs() {
+ // Currently not possible
+ return 0;
+ }
+
@Override
public Targetable getVTOLBombTarget() {
return bombTarget;
}
-
+
@Override
public void setVTOLBombTarget(Targetable t) {
bombTarget = t;
}
-
+
public List getStrafingCoords() {
return strafingCoords;
}
@@ -565,7 +602,7 @@ public PilotingRollData addEntityBonuses(PilotingRollData prd) {
@Override
public void newRound(int roundNumber) {
super.newRound(roundNumber);
-
+
bombTarget = null;
strafingCoords.clear();
}
diff --git a/megamek/src/megamek/common/actions/WeaponAttackAction.java b/megamek/src/megamek/common/actions/WeaponAttackAction.java
index d7e20f18d30..636e92d7dca 100644
--- a/megamek/src/megamek/common/actions/WeaponAttackAction.java
+++ b/megamek/src/megamek/common/actions/WeaponAttackAction.java
@@ -19,6 +19,7 @@
import megamek.common.*;
import megamek.common.enums.AimingMode;
import megamek.common.options.OptionsConstants;
+import megamek.common.weapons.DiveBombAttack;
import megamek.common.weapons.InfantryAttack;
import megamek.common.weapons.Weapon;
import megamek.common.weapons.artillery.ArtilleryCannonWeapon;
@@ -80,7 +81,7 @@ public class WeaponAttackAction extends AbstractAttackAction implements Serializ
private int swarmMissiles = 0;
// bomb stuff
- private int[] bombPayload = new int[BombType.B_NUM];
+ private HashMap bombPayloads = new HashMap();
// equipment that affects this attack (AMS, ECM?, etc)
// only used server-side
@@ -116,11 +117,15 @@ public class WeaponAttackAction extends AbstractAttackAction implements Serializ
public WeaponAttackAction(int entityId, int targetId, int weaponId) {
super(entityId, targetId);
this.weaponId = weaponId;
+ this.bombPayloads.put("internal", new int[BombType.B_NUM]);
+ this.bombPayloads.put("external", new int[BombType.B_NUM]);
}
public WeaponAttackAction(int entityId, int targetType, int targetId, int weaponId) {
super(entityId, targetType, targetId);
this.weaponId = weaponId;
+ this.bombPayloads.put("internal", new int[BombType.B_NUM]);
+ this.bombPayloads.put("external", new int[BombType.B_NUM]);
}
public int getWeaponId() {
@@ -1606,6 +1611,9 @@ private static String toHitIsImpossible(Game game, Entity ae, int attackerId, Ta
// Air-to-ground attacks
if (Compute.isAirToGround(ae, target) && !isArtilleryIndirect && !ae.isDropping()) {
+ if (ae.isBomber() && weapon.isInternalBomb() && ((IBomber)ae).getUsedInternalBombs() >= 6) {
+ return Messages.getString("WeaponAttackAction.AlreadyUsedMaxInternalBombs");
+ }
// Can't strike from above altitude 5. Dive bombing uses a different test below
if ((ae.getAltitude() > 5)
&& !wtype.hasFlag(WeaponType.F_DIVE_BOMB) && !wtype.hasFlag(WeaponType.F_ALT_BOMB)) {
@@ -1615,7 +1623,7 @@ private static String toHitIsImpossible(Game game, Entity ae, int attackerId, Ta
if ((ae.getAltitude() > 3) && isStrafing) {
return Messages.getString("WeaponAttackAction.AttackerTooHigh");
}
- // Additional Nape-of-Earth restrictions for strafing
+ // Additional Nap-of-Earth restrictions for strafing
if ((ae.getAltitude() == 1) && isStrafing) {
Vector passedThrough = ae.getPassedThrough();
if (passedThrough.isEmpty() || passedThrough.get(0).equals(target.getPosition())) {
@@ -2151,7 +2159,9 @@ private static String toHitIsImpossible(Game game, Entity ae, int attackerId, Ta
// Capital weapons fire by grounded units
if (wtype.isSubCapital() || wtype.isCapital()) {
// Can't fire any but capital/subcapital missiles surface to surface
+ // (but VTOL dive bombing is allowed)
if (Compute.isGroundToGround(ae, target)
+ && !((ae.getMovementMode() == EntityMovementMode.VTOL) && (wtype instanceof DiveBombAttack))
&& !(wtype instanceof CapitalMissileWeapon)) {
return Messages.getString("WeaponAttackAction.NoS2SCapWeapons");
}
@@ -2742,16 +2752,25 @@ public void setSwarmMissiles(int swarmMissiles) {
}
public int[] getBombPayload() {
+ int[] bombPayload = new int[BombType.B_NUM];
+ for (int i=0; i getBombPayloads() {
+ return bombPayloads;
+ }
+
/**
*
- * @param load This is the "bomb payload". It's an array indexed by the constants declared in BombType.
+ * @param bpls These are the "bomb payload" for internal and external bomb stores.
+ * It's a HashMap of two arrays, each indexed by the constants declared in BombType.
* Each element indicates how many types of that bomb should be fired.
*/
- public void setBombPayload(int[] load) {
- bombPayload = load;
+ public void setBombPayloads(HashMap bpls) {
+ bombPayloads = (HashMap) bpls.clone();
}
public boolean isStrafing() {
@@ -3593,7 +3612,7 @@ private static ToHitData compileAeroAttackerToHitMods(Game game, Entity ae, Targ
// So it's here instead of with other weapon mods that apply across the board
if ((wtype != null) &&
((wtype.ammoType == AmmoType.T_GAUSS_HEAVY) ||
- (wtype.ammoType == AmmoType.T_IGAUSS_HEAVY)) &&
+ (wtype.ammoType == AmmoType.T_IGAUSS_HEAVY)) &&
!(ae instanceof Dropship)
&& !(ae instanceof Jumpship)) {
toHit.addModifier(+1, Messages.getString("WeaponAttackAction.FighterHeavyGauss"));
diff --git a/megamek/src/megamek/common/loaders/BLKAeroFile.java b/megamek/src/megamek/common/loaders/BLKAeroSpaceFighterFile.java
similarity index 90%
rename from megamek/src/megamek/common/loaders/BLKAeroFile.java
rename to megamek/src/megamek/common/loaders/BLKAeroSpaceFighterFile.java
index 7593c43671d..d0a28609c65 100644
--- a/megamek/src/megamek/common/loaders/BLKAeroFile.java
+++ b/megamek/src/megamek/common/loaders/BLKAeroSpaceFighterFile.java
@@ -26,7 +26,7 @@
*
* @author taharqa
*/
-public class BLKAeroFile extends BLKFile implements IMechLoader {
+public class BLKAeroSpaceFighterFile extends BLKFile implements IMechLoader {
// armor locatioms
public static final int NOSE = 0;
@@ -34,14 +34,14 @@ public class BLKAeroFile extends BLKFile implements IMechLoader {
public static final int LW = 2;
public static final int AFT = 3;
- public BLKAeroFile(BuildingBlock bb) {
+ public BLKAeroSpaceFighterFile(BuildingBlock bb) {
dataFile = bb;
}
@Override
public Entity getEntity() throws EntityLoadingException {
- Aero a = new Aero();
+ AeroSpaceFighter a = new AeroSpaceFighter();
setBasicEntityData(a);
@@ -50,9 +50,6 @@ public Entity getEntity() throws EntityLoadingException {
}
a.setWeight(dataFile.getDataAsDouble("tonnage")[0]);
- // how many bombs can it carry
- a.autoSetMaxBombPoints();
-
// get a movement mode - lets try Aerodyne
EntityMovementMode nMotion = EntityMovementMode.AERODYNE;
a.setMovementMode(nMotion);
@@ -148,10 +145,10 @@ public Entity getEntity() throws EntityLoadingException {
throw new EntityLoadingException("Incorrect armor array length");
}
- a.initializeArmor(armor[BLKAeroFile.NOSE], Aero.LOC_NOSE);
- a.initializeArmor(armor[BLKAeroFile.RW], Aero.LOC_RWING);
- a.initializeArmor(armor[BLKAeroFile.LW], Aero.LOC_LWING);
- a.initializeArmor(armor[BLKAeroFile.AFT], Aero.LOC_AFT);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.NOSE], Aero.LOC_NOSE);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.RW], Aero.LOC_RWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.LW], Aero.LOC_LWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.AFT], Aero.LOC_AFT);
a.initializeArmor(0, Aero.LOC_WINGS);
a.initializeArmor(IArmorState.ARMOR_NA, Aero.LOC_FUSELAGE);
@@ -164,6 +161,9 @@ public Entity getEntity() throws EntityLoadingException {
// This is not working right for arrays for some reason
a.autoSetThresh();
+ // add Transporters prior to equipment to simplify F_CARGO bay assignment
+ addTransports(a);
+
for (int loc = 0; loc < a.locations(); loc++) {
loadEquipment(a, a.getLocationName(loc), loc);
}
@@ -175,7 +175,9 @@ public Entity getEntity() throws EntityLoadingException {
a.setOmni(true);
}
- addTransports(a);
+ // how many bombs can it carry; dependent on transport bays as well as total mass.
+ a.autoSetMaxBombPoints();
+
a.setArmorTonnage(a.getArmorWeight());
loadQuirks(a);
return a;
@@ -237,10 +239,10 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
facing = 2;
equipName = equipName.substring(0, equipName.length() - 4)
.trim();
- }
+ }
EquipmentType etype = EquipmentType.get(equipName);
-
+
if ((etype instanceof MiscType) && etype.hasFlag(MiscType.F_CASE)) {
if (etype.isClan() || addedCase) {
continue;
@@ -267,7 +269,7 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
Mounted mount = t.addEquipment(etype, useLoc, rearMount);
mount.setOmniPodMounted(omniMounted);
// Need to set facing for VGLs
- if ((etype instanceof WeaponType)
+ if ((etype instanceof WeaponType)
&& etype.hasFlag(WeaponType.F_VGL)) {
if (facing == -1) {
mount.setFacing(defaultAeroVGLFacing(useLoc, rearMount));
@@ -281,6 +283,11 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
}
mount.setSize(size);
}
+ if (etype.hasFlag(MiscType.F_CARGO)) {
+ // Treat F_CARGO equipment as cargo bays with 1 door, e.g. for ASF with IBB.
+ int idx = t.getTransportBays().size();
+ t.addTransporter(new CargoBay(mount.getSize(), 1, idx), omniMounted);
+ }
} catch (LocationFullException ex) {
throw new EntityLoadingException(ex.getMessage());
}
diff --git a/megamek/src/megamek/common/loaders/BLKConvFighterFile.java b/megamek/src/megamek/common/loaders/BLKConvFighterFile.java
index 33abea1effc..ce8e9bf143b 100644
--- a/megamek/src/megamek/common/loaders/BLKConvFighterFile.java
+++ b/megamek/src/megamek/common/loaders/BLKConvFighterFile.java
@@ -49,9 +49,6 @@ public Entity getEntity() throws EntityLoadingException {
}
a.setWeight(dataFile.getDataAsDouble("tonnage")[0]);
- // how many bombs can it carry
- a.autoSetMaxBombPoints();
-
// get a movement mode - lets try Aerodyne
EntityMovementMode nMotion = EntityMovementMode.AERODYNE;
a.setMovementMode(nMotion);
@@ -116,10 +113,10 @@ public Entity getEntity() throws EntityLoadingException {
throw new EntityLoadingException("Incorrect armor array length");
}
- a.initializeArmor(armor[BLKAeroFile.NOSE], Aero.LOC_NOSE);
- a.initializeArmor(armor[BLKAeroFile.RW], Aero.LOC_RWING);
- a.initializeArmor(armor[BLKAeroFile.LW], Aero.LOC_LWING);
- a.initializeArmor(armor[BLKAeroFile.AFT], Aero.LOC_AFT);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.NOSE], Aero.LOC_NOSE);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.RW], Aero.LOC_RWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.LW], Aero.LOC_LWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.AFT], Aero.LOC_AFT);
a.autoSetInternal();
a.recalculateTechAdvancement();
@@ -140,6 +137,10 @@ public Entity getEntity() throws EntityLoadingException {
}
addTransports(a);
+
+ // how many bombs can it carry; depends on transport space as well.
+ a.autoSetMaxBombPoints();
+
a.setArmorTonnage(a.getArmorWeight());
loadQuirks(a);
return a;
@@ -197,7 +198,7 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
facing = 2;
equipName = equipName.substring(0, equipName.length() - 4)
.trim();
- }
+ }
EquipmentType etype = EquipmentType.get(equipName);
@@ -214,7 +215,7 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
int useLoc = TestEntity.eqRequiresLocation(t, etype) ? nLoc : Aero.LOC_FUSELAGE;
Mounted mount = t.addEquipment(etype, useLoc, rearMount);
// Need to set facing for VGLs
- if ((etype instanceof WeaponType)
+ if ((etype instanceof WeaponType)
&& etype.hasFlag(WeaponType.F_VGL)) {
// If no facing specified, assume front
if (facing == -1) {
diff --git a/megamek/src/megamek/common/loaders/BLKDropshipFile.java b/megamek/src/megamek/common/loaders/BLKDropshipFile.java
index 5e6caa93d15..36dc5aa6cc2 100644
--- a/megamek/src/megamek/common/loaders/BLKDropshipFile.java
+++ b/megamek/src/megamek/common/loaders/BLKDropshipFile.java
@@ -13,7 +13,6 @@
*/
package megamek.common.loaders;
-import com.sun.mail.util.DecodingException;
import megamek.common.*;
import megamek.common.util.BuildingBlock;
@@ -167,10 +166,10 @@ public Entity getEntity() throws EntityLoadingException {
throw new EntityLoadingException("Incorrect armor array length");
}
- a.initializeArmor(armor[BLKAeroFile.NOSE], Dropship.LOC_NOSE);
- a.initializeArmor(armor[BLKAeroFile.RW], Dropship.LOC_RWING);
- a.initializeArmor(armor[BLKAeroFile.LW], Dropship.LOC_LWING);
- a.initializeArmor(armor[BLKAeroFile.AFT], Dropship.LOC_AFT);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.NOSE], Dropship.LOC_NOSE);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.RW], Dropship.LOC_RWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.LW], Dropship.LOC_LWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.AFT], Dropship.LOC_AFT);
a.initializeArmor(IArmorState.ARMOR_NA, Dropship.LOC_HULL);
a.autoSetInternal();
@@ -188,6 +187,9 @@ public Entity getEntity() throws EntityLoadingException {
addTransports(a);
+ // how many bombs can it carry; depends on transport bays
+ a.autoSetMaxBombPoints();
+
a.setArmorTonnage(a.getArmorWeight());
loadQuirks(a);
return a;
diff --git a/megamek/src/megamek/common/loaders/BLKFile.java b/megamek/src/megamek/common/loaders/BLKFile.java
index dbe02215953..85d7c5f6fd1 100644
--- a/megamek/src/megamek/common/loaders/BLKFile.java
+++ b/megamek/src/megamek/common/loaders/BLKFile.java
@@ -308,6 +308,11 @@ protected void loadEquipment(Entity t, String sName, int nLoc)
* ((InfantryWeapon) mount.getType()).getShots());
mount.getLinked().setShotsLeft(mount.getLinked().getOriginalShots());
}
+ if (etype.hasFlag(MiscType.F_CARGO)) {
+ // Treat F_CARGO equipment as cargo bays with 1 door, e.g. for ASF with IBB.
+ int idx = t.getTransportBays().size();
+ t.addTransporter(new CargoBay(mount.getSize(), 1, idx), isOmniMounted);
+ }
} catch (LocationFullException ex) {
throw new EntityLoadingException(ex.getMessage());
}
@@ -585,6 +590,8 @@ public static BuildingBlock getBlock(Entity t) {
blk.writeBlockData("UnitType", "Tank");
} else if (t instanceof Infantry) {
blk.writeBlockData("UnitType", "Infantry");
+ } else if (t instanceof AeroSpaceFighter) {
+ blk.writeBlockData("UnitType", "AeroSpaceFighter");
} else if (t instanceof Aero) {
blk.writeBlockData("UnitType", "Aero");
}
diff --git a/megamek/src/megamek/common/loaders/BLKFixedWingSupportFile.java b/megamek/src/megamek/common/loaders/BLKFixedWingSupportFile.java
index 64313fb5a7e..78eff20cc1c 100644
--- a/megamek/src/megamek/common/loaders/BLKFixedWingSupportFile.java
+++ b/megamek/src/megamek/common/loaders/BLKFixedWingSupportFile.java
@@ -118,11 +118,11 @@ public Entity getEntity() throws EntityLoadingException {
throw new EntityLoadingException("Incorrect armor array length");
}
- a.initializeArmor(armor[BLKAeroFile.NOSE], Aero.LOC_NOSE);
- a.initializeArmor(armor[BLKAeroFile.RW], Aero.LOC_RWING);
- a.initializeArmor(armor[BLKAeroFile.LW], Aero.LOC_LWING);
- a.initializeArmor(armor[BLKAeroFile.AFT], Aero.LOC_AFT);
-
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.NOSE], Aero.LOC_NOSE);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.RW], Aero.LOC_RWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.LW], Aero.LOC_LWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.AFT], Aero.LOC_AFT);
+
// Set the structural tech rating
if (!dataFile.exists("structural_tech_rating")) {
throw new EntityLoadingException("Could not find " +
@@ -133,12 +133,12 @@ public Entity getEntity() throws EntityLoadingException {
// Set armor tech rating, if it exists (defaults to structural tr)
if (dataFile.exists("armor_tech_rating")) {
a.setArmorTechRating(dataFile
- .getDataAsInt("armor_tech_rating")[0]);
+ .getDataAsInt("armor_tech_rating")[0]);
}
- // Set engine tech rating, if it exists (defaults to structural tr)
+ // Set engine tech rating, if it exists (defaults to structural tr)
if (dataFile.exists("engine_tech_rating")) {
a.setEngineTechRating(dataFile
- .getDataAsInt("engine_tech_rating")[0]);
+ .getDataAsInt("engine_tech_rating")[0]);
}
a.autoSetInternal();
@@ -225,7 +225,7 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
facing = 2;
equipName = equipName.substring(0, equipName.length() - 4)
.trim();
- }
+ }
EquipmentType etype = EquipmentType.get(equipName);
@@ -242,7 +242,7 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
Mounted mount = t.addEquipment(etype, nLoc, rearMount);
mount.setOmniPodMounted(omniMounted);
// Need to set facing for VGLs
- if ((etype instanceof WeaponType)
+ if ((etype instanceof WeaponType)
&& etype.hasFlag(WeaponType.F_VGL)) {
if (facing == -1) {
mount.setFacing(defaultAeroVGLFacing(nLoc, rearMount));
diff --git a/megamek/src/megamek/common/loaders/BLKSmallCraftFile.java b/megamek/src/megamek/common/loaders/BLKSmallCraftFile.java
index b854a9257c7..788397fc95d 100644
--- a/megamek/src/megamek/common/loaders/BLKSmallCraftFile.java
+++ b/megamek/src/megamek/common/loaders/BLKSmallCraftFile.java
@@ -149,10 +149,10 @@ public Entity getEntity() throws EntityLoadingException {
throw new EntityLoadingException("Incorrect armor array length");
}
- a.initializeArmor(armor[BLKAeroFile.NOSE], SmallCraft.LOC_NOSE);
- a.initializeArmor(armor[BLKAeroFile.RW], SmallCraft.LOC_RWING);
- a.initializeArmor(armor[BLKAeroFile.LW], SmallCraft.LOC_LWING);
- a.initializeArmor(armor[BLKAeroFile.AFT], SmallCraft.LOC_AFT);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.NOSE], SmallCraft.LOC_NOSE);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.RW], SmallCraft.LOC_RWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.LW], SmallCraft.LOC_LWING);
+ a.initializeArmor(armor[BLKAeroSpaceFighterFile.AFT], SmallCraft.LOC_AFT);
a.initializeArmor(IArmorState.ARMOR_NA, SmallCraft.LOC_HULL);
a.autoSetInternal();
@@ -165,6 +165,10 @@ public Entity getEntity() throws EntityLoadingException {
}
addTransports(a);
+
+ // how many bombs can it carry; depends on transport bays
+ a.autoSetMaxBombPoints();
+
a.setArmorTonnage(a.getArmorWeight());
loadQuirks(a);
return a;
@@ -222,7 +226,7 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
facing = 2;
equipName = equipName.substring(0, equipName.length() - 4)
.trim();
- }
+ }
EquipmentType etype = EquipmentType.get(equipName);
@@ -239,7 +243,7 @@ protected void loadEquipment(Entity t, String sName, int nLoc) throws EntityLoad
int useLoc = TestEntity.eqRequiresLocation(t, etype) ? nLoc : SmallCraft.LOC_HULL;
Mounted mount = t.addEquipment(etype, useLoc, rearMount);
// Need to set facing for VGLs
- if ((etype instanceof WeaponType)
+ if ((etype instanceof WeaponType)
&& etype.hasFlag(WeaponType.F_VGL)) {
if (facing == -1) {
mount.setFacing(defaultAeroVGLFacing(useLoc, rearMount));
diff --git a/megamek/src/megamek/common/templates/TROView.java b/megamek/src/megamek/common/templates/TROView.java
index 7b5fa393f27..b9aa374e8e1 100644
--- a/megamek/src/megamek/common/templates/TROView.java
+++ b/megamek/src/megamek/common/templates/TROView.java
@@ -404,6 +404,7 @@ protected int addEquipment(Entity entity, boolean includeAmmo) {
final int structure = entity.getStructureType();
final Map> equipment = new HashMap<>();
int nameWidth = 20;
+ EquipmentKey eqk;
for (final Mounted m : entity.getEquipment()) {
if (skipMount(m, includeAmmo)) {
continue;
@@ -422,8 +423,8 @@ protected int addEquipment(Entity entity, boolean includeAmmo) {
if (m.isOmniPodMounted() || !entity.isOmni()) {
final String loc = formatLocationTableEntry(entity, m);
equipment.putIfAbsent(loc, new HashMap<>());
- equipment.get(loc).merge(new EquipmentKey(m.getType(), m.getSize(), m.isArmored()),
- 1, Integer::sum);
+ eqk = new EquipmentKey(m.getType(), m.getSize(), m.isArmored(), m.isInternalBomb());
+ equipment.get(loc).merge(eqk,1, Integer::sum);
}
}
final List