diff --git a/megamek/src/megamek/client/bot/CEntity.java b/megamek/src/megamek/client/bot/CEntity.java index 2874aae4475..7d33461dea2 100644 --- a/megamek/src/megamek/client/bot/CEntity.java +++ b/megamek/src/megamek/client/bot/CEntity.java @@ -1838,7 +1838,7 @@ private static double[] getExpectedDamage(Infantry attacker, int gunskill) { // If there are two secondary weapons per squad then use that weapons // range. Otherwise use the primary weapons range. - if ((null != secondary_weapon) && (attacker.getSecondaryN() >= 2)) { + if ((null != secondary_weapon) && (attacker.getSecondaryWeaponsPerSquad() >= 2)) { base_range = secondary_weapon.getInfantryRange(); } else { base_range = primary_weapon.getInfantryRange(); diff --git a/megamek/src/megamek/client/ui/swing/EquipChoicePanel.java b/megamek/src/megamek/client/ui/swing/EquipChoicePanel.java index 10f5a5678c8..984c193c65e 100644 --- a/megamek/src/megamek/client/ui/swing/EquipChoicePanel.java +++ b/megamek/src/megamek/client/ui/swing/EquipChoicePanel.java @@ -244,7 +244,7 @@ public EquipChoicePanel(Entity entity, ClientGUI clientgui, Client client) { // Can't set up munitions on infantry. if (!((entity instanceof Infantry) && !((Infantry) entity) - .hasFieldGun()) || (entity instanceof BattleArmor)) { + .hasFieldWeapon()) || (entity instanceof BattleArmor)) { setupMunitions(); panMunitions.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), Messages.getString("CustomMechDialog.MunitionsPanelTitle"), diff --git a/megamek/src/megamek/client/ui/swing/UnitEditorDialog.java b/megamek/src/megamek/client/ui/swing/UnitEditorDialog.java index 57905e53808..7342f8d21e2 100644 --- a/megamek/src/megamek/client/ui/swing/UnitEditorDialog.java +++ b/megamek/src/megamek/client/ui/swing/UnitEditorDialog.java @@ -281,7 +281,7 @@ private void initInfantryArmorPanel() { int men = Math.max(infantry.getShootingStrength(), 0); spnInternal[0] = new JSpinner(new SpinnerNumberModel(men, 0, - infantry.getSquadN() * infantry.getSquadSize(), 1)); + infantry.getSquadCount() * infantry.getSquadSize(), 1)); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; @@ -1190,7 +1190,7 @@ private void btnOkayActionPerformed(java.awt.event.ActionEvent evt) { } } if (entity instanceof Infantry) { - ((Infantry) entity).damageOrRestoreFieldGunsAndArty(); + ((Infantry) entity).damageOrRestoreFieldWeapons(); entity.applyDamage(); } diff --git a/megamek/src/megamek/client/ui/swing/boardview/EntitySprite.java b/megamek/src/megamek/client/ui/swing/boardview/EntitySprite.java index dd5e53a43e7..c303fd95c20 100644 --- a/megamek/src/megamek/client/ui/swing/boardview/EntitySprite.java +++ b/megamek/src/megamek/client/ui/swing/boardview/EntitySprite.java @@ -700,7 +700,7 @@ public void prepare() { // draw facing graph.setColor(Color.white); if ((entity.getFacing() != -1) - && !(isInfantry && !((Infantry) entity).hasFieldGun() + && !(isInfantry && !((Infantry) entity).hasFieldWeapon() && !((Infantry) entity).isTakingCover()) && !(isAero && ((IAero) entity).isSpheroid() && !board.inSpace())) { // Indicate a stacked unit with the same facing that can still move diff --git a/megamek/src/megamek/common/BattleArmor.java b/megamek/src/megamek/common/BattleArmor.java index 82f64e61f02..c90226fce70 100644 --- a/megamek/src/megamek/common/BattleArmor.java +++ b/megamek/src/megamek/common/BattleArmor.java @@ -24,8 +24,7 @@ import org.apache.logging.log4j.LogManager; import java.text.NumberFormat; -import java.util.Arrays; -import java.util.Vector; +import java.util.*; /** * This class represents a squad or point of battle armor equipped infantry, @@ -341,7 +340,7 @@ public BattleArmor() { setArmorType(EquipmentType.T_ARMOR_BA_STANDARD); // BA are always one squad - squadn = 1; + squadCount = 1; // All Battle Armor squads are Clan until specified otherwise. setTechLevel(TechConstants.T_CLAN_TW); @@ -736,16 +735,6 @@ public HitData getTransferLocation(HitData hit) { return new HitData(Entity.LOC_DESTROYED); } - /** - * Battle Armor units use default behavior for armor and internals. - * - * @see megamek.common.Infantry#isPlatoon() - */ - @Override - protected boolean isPlatoon() { - return false; - } - /** * Battle Armor units have no armor on their squad location. * @@ -2214,8 +2203,7 @@ public int getSpriteDrawPriority() { } @Override - public void damageOrRestoreFieldGunsAndArty() { } - - @Override - protected void damageFieldGunsAndArty() { } + protected boolean isFieldWeapon(Mounted equipment) { + return false; + } } diff --git a/megamek/src/megamek/common/BattleForceElement.java b/megamek/src/megamek/common/BattleForceElement.java new file mode 100644 index 00000000000..e69de29bb2d diff --git a/megamek/src/megamek/common/Compute.java b/megamek/src/megamek/common/Compute.java index 8463fd8286f..1e6e408ad0a 100644 --- a/megamek/src/megamek/common/Compute.java +++ b/megamek/src/megamek/common/Compute.java @@ -7043,7 +7043,7 @@ public static int getFullCrewSize(Entity entity) { } return ntroopers; } else if (entity instanceof Infantry) { - return ((Infantry) entity).getSquadN() * ((Infantry) entity).getSquadSize(); + return ((Infantry) entity).getSquadCount() * ((Infantry) entity).getSquadSize(); } else if (entity instanceof Jumpship || entity instanceof SmallCraft) { return getAeroCrewNeeds(entity) + getTotalGunnerNeeds(entity); } else { diff --git a/megamek/src/megamek/common/Infantry.java b/megamek/src/megamek/common/Infantry.java index 8665957972f..3e0146996e3 100644 --- a/megamek/src/megamek/common/Infantry.java +++ b/megamek/src/megamek/common/Infantry.java @@ -31,27 +31,22 @@ import java.text.NumberFormat; import java.util.*; -import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; /** - * This class represents the lowest of the low, the ground pounders, the city - * rats, the PBI (Poor Bloody Infantry).

PLEASE NOTE!!! This class just - * represents unarmored infantry platoons as described by CitiTech (c) 1986. - * I've never seen the rules for powered armor, "anti-mech" troops, or - * Immortals. + * This class represents Conventional Infantry (with BattleArmor as a subclass). + * The lowest of the low, the ground pounders, the city rats, the PBI (Poor Bloody Infantry). * - * PLEASE NOTE!!! My programming style is to put constants first in tests so the - * compiler catches my "= for ==" errors. + * Note that BattleArmor extends Infantry! * * @author Suvarov454@sourceforge.net (James A. Damour) */ public class Infantry extends Entity { private static final long serialVersionUID = -8706716079307721282L; - /** - * Infantry Specializations - */ - public static int BRIDGE_ENGINEERS = 1 << 0; + // Infantry Specializations + public static int BRIDGE_ENGINEERS = 1; public static int DEMO_ENGINEERS = 1 << 1; public static int FIRE_ENGINEERS = 1 << 2; public static int MINE_ENGINEERS = 1 << 3; @@ -65,47 +60,28 @@ public class Infantry extends Entity { public static int XCT = 1 << 11; public static int SCUBA = 1 << 12; public static int NUM_SPECIALIZATIONS = 13; - public static int COMBAT_ENGINEERS = BRIDGE_ENGINEERS | DEMO_ENGINEERS - | FIRE_ENGINEERS | MINE_ENGINEERS | SENSOR_ENGINEERS - | TRENCH_ENGINEERS; - - /** - * squad size and number - */ - protected int squadn = 1; - private int squadsize = 1; + public static int COMBAT_ENGINEERS = BRIDGE_ENGINEERS | DEMO_ENGINEERS | FIRE_ENGINEERS | MINE_ENGINEERS + | SENSOR_ENGINEERS | TRENCH_ENGINEERS; - /** - * The number of men originally in this platoon. - */ - protected int menStarting = 0; + protected int squadCount = 1; + private int squadSize = 1; + protected int originalTrooperCount; - /** - * The number of men alive in this platoon at the beginning of the phase, - * before it begins to take damage. - */ - private int menShooting = 0; + /** The number of troopers alive in this platoon at the beginning of the phase, before taking damage. */ + private int troopersShooting; - /** - * The number of men left alive in this platoon. - */ - private int men = 0; + /** The number of troopers alive in this platoon, including any damage sustained in the current phase. */ + private int activeTroopers; - /** - * Information on primary and secondary weapons - * This must be kept separate from the equipment array - * because they are not fired as separate weapons - */ - private transient InfantryWeapon primaryW; + // Information on primary and secondary weapons. This must be kept separate from the equipment array + // because they are not fired as separate weapons + private InfantryWeapon primaryWeapon; private String primaryName; - private transient InfantryWeapon secondW; + private InfantryWeapon secondaryWeapon; private String secondName; - private int secondn = 0; + private int secondaryWeaponsPerSquad = 0; - - /** - * Infantry armor - */ + // Armor private double damageDivisor = 1.0; private boolean encumbering = false; private boolean spaceSuit = false; @@ -114,55 +90,40 @@ public class Infantry extends Entity { private boolean sneak_ir = false; private boolean sneak_ecm = false; - /** - * Stores which infantry specializations are active. - */ + /** The active specializations of this platoon. */ private int infSpecs = 0; /** * For mechanized VTOL infantry, stores whether the platoon are microlite troops, * which need to enter a hex every turn to remain in flight. */ - private boolean microlite = false; + private boolean isMicrolite = false; - /** - * The location for infantry equipment. - */ public static final int LOC_INFANTRY = 0; public static final int LOC_FIELD_GUNS = 1; - /** - * Infantry only have critical slots for field gun ammo - */ + // Infantry only have critical slots for field gun ammo private static final int[] NUM_OF_SLOTS = { 20, 20 }; - private static final String[] LOCATION_ABBRS = { "MEN", "FGUN" }; - private static final String[] LOCATION_NAMES = { "Men", "Field Guns"}; + private static final String[] LOCATION_ABBRS = { "TPRS", "FGUN" }; + private static final String[] LOCATION_NAMES = { "Troopers", "Field Guns" }; public int turnsLayingExplosives = -1; public static final int DUG_IN_NONE = 0; public static final int DUG_IN_WORKING = 1; // no protection, can't attack public static final int DUG_IN_COMPLETE = 2; // protected, restricted arc - public static final int DUG_IN_FORTIFYING1 = 3; // no protection, can't - // attack - public static final int DUG_IN_FORTIFYING2 = 4; // no protection, can't - // attack + public static final int DUG_IN_FORTIFYING1 = 3; // no protection, can't attack + public static final int DUG_IN_FORTIFYING2 = 4; // no protection, can't attack private int dugIn = DUG_IN_NONE; private boolean isTakingCover = false; private boolean canCallSupport = true; private boolean isCallingSupport = false; - // Public and Protected constants, constructors, and methods. - - /** - * The maximum number of men in an infantry platoon. - */ + /** The maximum number of troopers in an infantry platoon. */ public static final int INF_PLT_MAX_MEN = 30; - /** - * The internal names of the anti-Mek attacks. - */ + // Anti-Mek attacks public static final String LEG_ATTACK = "LegAttack"; public static final String SWARM_MEK = "SwarmMek"; public static final String SWARM_WEAPON_MEK = "SwarmWeaponMek"; @@ -182,27 +143,19 @@ public String[] getLocationNames() { return LOCATION_NAMES; } - /** - * Returns the number of locations in this platoon - */ @Override public int locations() { return 2; } - /** - * Generate a new, blank, infantry platoon. Hopefully, we'll be loaded from - * somewhere. - */ + /** Generate a new, blank, infantry platoon. Hopefully, we'll be loaded from somewhere. */ public Infantry() { - // Instantiate the superclass. super(); // Create a "dead" leg rifle platoon. - menStarting = 0; - menShooting = 0; - men = 0; + originalTrooperCount = 0; + troopersShooting = 0; + activeTroopers = 0; setMovementMode(EntityMovementMode.INF_LEG); - // Determine the number of MPs. setOriginalWalkMP(1); } @@ -359,33 +312,22 @@ protected void addSystemTechAdvancement(CompositeTechLevel ctl) { } } - /** - * Infantry can face freely (except when dug in) - */ @Override public boolean canChangeSecondaryFacing() { return !hasActiveFieldArtillery(); } - /** - * Infantry can face freely - */ @Override public boolean isValidSecondaryFacing(int dir) { return true; } - /** - * Infantry can face freely - */ @Override public int clipSecondaryFacing(int dir) { return dir; } - /** - * Create local platoon for Urban Guerrilla - */ + /** Creates a local platoon for Urban Guerrilla. */ public void createLocalSupport() { if (Compute.isInUrbanEnvironment(game, getPosition())) { setIsCallingSupport(true); @@ -401,22 +343,19 @@ public boolean getIsCallingSupport() { return isCallingSupport; } - /** - * return this infantry's walk mp, adjusted for planetary conditions - */ @Override public int getWalkMP(boolean gravity, boolean ignoreheat, boolean ignoremodulararmor) { int mp = getOriginalWalkMP(); - // encumbering armor reduces MP by 1 to a minimum of one (TacOps, pg. 318) + // Encumbering armor (TacOps, pg. 318) if (encumbering) { mp = Math.max(mp - 1, 1); } - if ((getSecondaryN() > 1) + if ((getSecondaryWeaponsPerSquad() > 1) && !hasAbility(OptionsConstants.MD_TSM_IMPLANT) && !hasAbility(OptionsConstants.MD_DERMAL_ARMOR) - && (null != secondW) && secondW.hasFlag(WeaponType.F_INF_SUPPORT) - && (getMovementMode() != EntityMovementMode.TRACKED) - && (getMovementMode() != EntityMovementMode.INF_JUMP)) { + && (null != secondaryWeapon) && secondaryWeapon.hasFlag(WeaponType.F_INF_SUPPORT) + && !getMovementMode().isTracked() + && !getMovementMode().isJumpInfantry()) { mp = Math.max(mp - 1, 0); } // PL-MASC IntOps p.84 @@ -428,12 +367,10 @@ && isConventionalInfantry()) { } if ((null != getCrew()) && hasAbility(OptionsConstants.INFANTRY_FOOT_CAV) - && ((getMovementMode() == EntityMovementMode.INF_LEG) - || (getMovementMode() == EntityMovementMode.INF_JUMP))) { + && ((getMovementMode().isLegInfantry()) || (getMovementMode().isJumpInfantry()))) { mp += 1; } if (hasActiveFieldArtillery()) { - //mp of 1 at the most mp = Math.min(mp, 1); } if (null != game) { @@ -448,71 +385,51 @@ && isConventionalInfantry()) { return mp; } - /** - * Return this Infantry's run MP, which is identical to its walk MP - */ @Override public int getRunMP(boolean gravity, boolean ignoreheat, boolean ignoremodulararmor) { - if ( (game != null) + int walkMP = getWalkMP(gravity, ignoreheat, ignoremodulararmor); + if ((game != null) && game.getOptions().booleanOption(OptionsConstants.ADVGRNDMOV_TACOPS_FAST_INFANTRY_MOVE)) { - if (getWalkMP(gravity, ignoreheat, ignoremodulararmor) > 0) { - return getWalkMP(gravity, ignoreheat, ignoremodulararmor) + 1; - } - return getWalkMP(gravity, ignoreheat, ignoremodulararmor) + 2; + return (walkMP > 0) ? walkMP + 1 : walkMP + 2; + } else { + return walkMP; } - return getWalkMP(gravity, ignoreheat, ignoremodulararmor); } - /** - * Infantry don't have MASC - */ @Override public int getRunMPwithoutMASC(boolean gravity, boolean ignoreheat, boolean ignoremodulararmor) { return getRunMP(gravity, ignoreheat, ignoremodulararmor); } - - /* - * (non-Javadoc) - * @see megamek.common.Entity#getJumpMP(boolean) - */ @Override public int getJumpMP(boolean gravity) { - int mp = 0; - if (getMovementMode() != EntityMovementMode.INF_UMU - && getMovementMode() != EntityMovementMode.SUBMARINE) { - mp = getOriginalJumpMP(); - } - if ((getSecondaryN() > 1) + int mp = hasUMU() ? 0 : getOriginalJumpMP(); + if ((getSecondaryWeaponsPerSquad() > 1) && !hasAbility(OptionsConstants.MD_TSM_IMPLANT) && !hasAbility(OptionsConstants.MD_DERMAL_ARMOR) - && (getMovementMode() != EntityMovementMode.SUBMARINE) - && (null != secondW) && secondW.hasFlag(WeaponType.F_INF_SUPPORT)) { + && !getMovementMode().isSubmarine() + && (null != secondaryWeapon) && secondaryWeapon.hasFlag(WeaponType.F_INF_SUPPORT)) { mp = Math.max(mp - 1, 0); - } else if (movementMode.equals(EntityMovementMode.VTOL) && getSecondaryN() > 0) { + } else if (movementMode.isVTOL() && getSecondaryWeaponsPerSquad() > 0) { mp = Math.max(mp - 1, 0); } if (gravity) { mp = applyGravityEffectsOnMP(mp); } - int windP = 0; if (null != game) { int windCond = game.getPlanetaryConditions().getWindStrength(); - if (windCond == PlanetaryConditions.WI_MOD_GALE) { - windP++; - } if (windCond >= PlanetaryConditions.WI_STRONG_GALE) { return 0; + } else if (windCond == PlanetaryConditions.WI_MOD_GALE) { + mp--; } } - mp = Math.max(mp - windP, 0); - return mp; + return Math.max(mp, 0); } @Override public boolean hasUMU() { - return getMovementMode().equals(EntityMovementMode.INF_UMU) - || getMovementMode().equals(EntityMovementMode.SUBMARINE); + return getMovementMode().isUMUInfantry() || getMovementMode().isSubmarine(); } @Override @@ -522,11 +439,7 @@ public int getActiveUMUCount() { @Override public int getAllUMUCount() { - if (hasUMU()) { - return jumpMP; - } else { - return 0; - } + return hasUMU() ? jumpMP : 0; } @Override @@ -536,13 +449,9 @@ public boolean antiTSMVulnerable() { } EquipmentType armorKit = getArmorKit(); return (armorKit == null) - || !armorKit.hasSubType(MiscType.S_SPACE_SUIT | MiscType.S_XCT_VACUUM - | MiscType.S_TOXIC_ATMO); + || !armorKit.hasSubType(MiscType.S_SPACE_SUIT | MiscType.S_XCT_VACUUM | MiscType.S_TOXIC_ATMO); } - /** - * Infantry can not enter water unless they have UMU mp or hover. - */ @Override public boolean isLocationProhibited(Coords c, int currElevation) { // Coords off the board aren't legal @@ -550,10 +459,8 @@ public boolean isLocationProhibited(Coords c, int currElevation) { return true; } Hex hex = game.getBoard().getHex(c); - // Taharqa: waiting to hear back from Welshie but I am going to assume - // that units pulling artillery - // should be treated as wheeled rather than motorized because otherwise - // mechanized units face fewer + // Taharqa: waiting to hear back from Welshie but I am going to assume that units pulling artillery + // should be treated as wheeled rather than motorized because otherwise mechanized units face fewer // terrain restrictions when pulling field artillery if (hex.containsTerrain(Terrains.IMPASSABLE)) { @@ -569,15 +476,12 @@ public boolean isLocationProhibited(Coords c, int currElevation) { // Additional restrictions for hidden units if (isHidden()) { // Can't deploy in paved hexes - if ((hex.containsTerrain(Terrains.PAVEMENT) - || hex.containsTerrain(Terrains.ROAD)) - && (!hex.containsTerrain(Terrains.BUILDING) - && !hex.containsTerrain(Terrains.RUBBLE))) { + if ((hex.containsTerrain(Terrains.PAVEMENT) || hex.containsTerrain(Terrains.ROAD)) + && (!hex.containsTerrain(Terrains.BUILDING) && !hex.containsTerrain(Terrains.RUBBLE))) { return true; } // Can't deploy on a bridge - if ((hex.terrainLevel(Terrains.BRIDGE_ELEV) == currElevation) - && hex.containsTerrain(Terrains.BRIDGE)) { + if ((hex.terrainLevel(Terrains.BRIDGE_ELEV) == currElevation) && hex.containsTerrain(Terrains.BRIDGE)) { return true; } // Can't deploy on the surface of water @@ -590,7 +494,7 @@ public boolean isLocationProhibited(Coords c, int currElevation) { return true; } - if (getMovementMode() == EntityMovementMode.WHEELED) { + if (getMovementMode().isWheeled()) { if (hex.containsTerrain(Terrains.WOODS) || hex.containsTerrain(Terrains.ROUGH) || hex.containsTerrain(Terrains.RUBBLE) @@ -601,7 +505,7 @@ public boolean isLocationProhibited(Coords c, int currElevation) { } } - if (getMovementMode() == EntityMovementMode.TRACKED) { + if (getMovementMode().isTracked()) { if ((hex.terrainLevel(Terrains.WOODS) > 1) || hex.containsTerrain(Terrains.JUNGLE) || (hex.terrainLevel(Terrains.ROUGH) > 1) @@ -610,7 +514,7 @@ public boolean isLocationProhibited(Coords c, int currElevation) { } } - if (getMovementMode() == EntityMovementMode.HOVER) { + if (getMovementMode().isHover()) { if (hex.containsTerrain(Terrains.WOODS) || hex.containsTerrain(Terrains.JUNGLE) || (hex.terrainLevel(Terrains.ROUGH) > 1) @@ -619,27 +523,17 @@ public boolean isLocationProhibited(Coords c, int currElevation) { } } - if (hex.terrainLevel(Terrains.WATER) <= 0 - && getMovementMode() == EntityMovementMode.SUBMARINE) { + if ((hex.terrainLevel(Terrains.WATER) <= 0) && getMovementMode().isSubmarine()) { return true; } - if ((hex.terrainLevel(Terrains.WATER) > 0) - && !hex.containsTerrain(Terrains.ICE)) { - if ((getMovementMode() == EntityMovementMode.HOVER) - || (getMovementMode() == EntityMovementMode.INF_UMU) - || (getMovementMode() == EntityMovementMode.SUBMARINE) - || (getMovementMode() == EntityMovementMode.VTOL)) { - return false; - } - return true; + if ((hex.terrainLevel(Terrains.WATER) > 0) && !hex.containsTerrain(Terrains.ICE)) { + return !getMovementMode().isHover() && !getMovementMode().isUMUInfantry() + && !getMovementMode().isSubmarine() && !getMovementMode().isVTOL(); } return false; } - /** - * Returns the name of the type of movement used. This is Infantry-specific. - */ @Override public String getMovementString(EntityMovementType mtype) { switch (mtype) { @@ -670,10 +564,6 @@ public String getMovementString(EntityMovementType mtype) { } } - /** - * Returns the abbreviation of the type of movement used. This is - * Infantry-specific. - */ @Override public String getMovementAbbr(EntityMovementType mtype) { switch (mtype) { @@ -701,12 +591,8 @@ public String getMovementAbbr(EntityMovementType mtype) { } } - /** - * Infantry only have one hit location. - */ @Override - public HitData rollHitLocation(int table, int side, int aimedLocation, AimingMode aimingMode, - int cover) { + public HitData rollHitLocation(int table, int side, int aimedLocation, AimingMode aimingMode, int cover) { return rollHitLocation(table, side); } @@ -715,170 +601,115 @@ public HitData rollHitLocation(int table, int side) { return new HitData(LOC_INFANTRY); } - /** - * Infantry only have one hit location. - */ @Override public HitData getTransferLocation(HitData hit) { return new HitData(Entity.LOC_DESTROYED); } - /** - * Gets the location that is destroyed recursively. - */ @Override public int getDependentLocation(int loc) { return Entity.LOC_NONE; } - /** - * Infantry have no rear armor. - */ @Override public boolean hasRearArmor(int loc) { return false; } - /** - * Infantry platoons do wierd and wacky things with armor and internals, but - * not all Infantry objects are platoons. - * - * @see megamek.common.BattleArmor#isPlatoon() - */ - protected boolean isPlatoon() { - return true; - } - - /** - * Returns the number of men left in the platoon, or - * IArmorState.ARMOR_DESTROYED. - */ @Override public int getInternal(int loc) { - if (!isPlatoon()) { + if (!isConventionalInfantry()) { return super.getInternal(loc); } if (loc != LOC_INFANTRY) { return 0; } - return (men > 0 ? men : IArmorState.ARMOR_DESTROYED); + return (activeTroopers > 0 ? activeTroopers : IArmorState.ARMOR_DESTROYED); } - /** - * Returns the number of men originally the platoon. - */ @Override public int getOInternal(int loc) { - if (!isPlatoon()) { - return super.getOInternal(loc); - } - return menStarting; + return isConventionalInfantry() ? originalTrooperCount : super.getOInternal(loc); } - /** - * Sets the amount of men remaining in the platoon. - */ @Override public void setInternal(int val, int loc) { super.setInternal(val, loc); if (loc == LOC_INFANTRY) { - men = val; - damageFieldGunsAndArty(); + activeTroopers = Math.max(val, 0); + damageFieldWeapons(); } } /** - * Returns the percent of the men remaining in the platoon. + * Returns the percent of the troopers remaining in the platoon. */ @Override public double getInternalRemainingPercent() { - if (!isPlatoon()) { + if (isConventionalInfantry()) { + return (double) Math.max(activeTroopers, 0) / originalTrooperCount; + } else { return super.getInternalRemainingPercent(); } - int menTotal = men > 0 ? men : 0; // Handle "DESTROYED" - return ((double) menTotal / menStarting); } /** - * Initializes the number of men in the platoon. Sets the original and + * Initializes the number of troopers in the platoon. Sets the original and * starting point of the platoon to the same number. */ @Override public void initializeInternal(int val, int loc) { if (loc == LOC_INFANTRY) { - menStarting = val; - menShooting = val; + originalTrooperCount = val; + troopersShooting = val; } super.initializeInternal(val, loc); } @Override public void autoSetInternal() { - initializeInternal(squadsize * squadn, LOC_INFANTRY); + initializeInternal(squadSize * squadCount, LOC_INFANTRY); } - /** - * Infantry can fire all around themselves. But field guns are set up to a - * vehicular turret facing - */ @Override public int getWeaponArc(int wn) { - Mounted mounted = getEquipment(wn); - if (mounted.getLocation() == LOC_FIELD_GUNS) { + Mounted weapon = getEquipment(wn); + // Infantry can fire all around themselves. But field guns are set up to a vehicular turret facing + if (isFieldWeapon(weapon)) { if (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_VEHICLE_ARCS)) { return Compute.ARC_TURRET; } return Compute.ARC_FORWARD; } - //This is interesting, according to TacOps rules, Dug in units no longer - //have to declare a facing + // According to TacOps rules, dug-in units no longer have to declare a facing return Compute.ARC_360; } - /** - * Infantry can fire all around themselves. But field guns act like turret - * mounted on a tank - */ @Override public boolean isSecondaryArcWeapon(int wn) { - return (getEquipment(wn).getLocation() == LOC_FIELD_GUNS) && !hasActiveFieldArtillery(); + return isFieldWeapon((getEquipment(wn))) && !hasActiveFieldArtillery(); } - /** - * Infantry build no heat. - */ @Override public int getHeatCapacity(boolean radicalHeatSinks) { return DOES_NOT_TRACK_HEAT; } - /** - * Infantry build no heat. - */ @Override public int getHeatCapacityWithWater() { return getHeatCapacity(); } - /** - * Infantry build no heat. - */ @Override public int getEngineCritHeat() { return 0; } - /** - * Infantry have no critical slots. - */ @Override protected int[] getNoOfSlots() { return NUM_OF_SLOTS; } - /** - * Infantry criticals can't be hit. - */ public boolean hasHittableCriticals(int loc) { return false; } @@ -925,30 +756,20 @@ public Vector victoryReport() { return vDesc; } - /** - * Infantry don't need piloting rolls. - */ @Override public PilotingRollData addEntityBonuses(PilotingRollData prd) { return prd; } - /** - * Infantry can only change 1 elevation level at a time unless Mountain Inf - * which is 3. - */ @Override public int getMaxElevationChange() { - if (hasSpecialization(MOUNTAIN_TROOPS)) { - return 3; - } - return 1; + return hasSpecialization(MOUNTAIN_TROOPS) ? 3 : 1; } @Override public void applyDamage() { super.applyDamage(); - menShooting = men; + troopersShooting = activeTroopers; } /** @@ -957,15 +778,11 @@ public void applyDamage() { * damage is removed from the unit. * Only affects Conventional Infantry, not BattleArmor (can be called safely on BA). */ - protected void damageFieldGunsAndArty() { + protected void damageFieldWeapons() { int totalCrewNeeded = 0; - List filteredWeaponList = new ArrayList<>(weaponList); - filteredWeaponList.removeIf(weapon -> weapon.getLocation() != LOC_FIELD_GUNS); - filteredWeaponList.removeIf(weapon -> !(weapon.getType() instanceof WeaponType)); - filteredWeaponList.removeIf(Mounted::isDestroyed); - for (Mounted weapon : filteredWeaponList) { - totalCrewNeeded += requiredCrewForFieldGun((WeaponType) weapon.getType()); - if (totalCrewNeeded > men) { + for (Mounted weapon : activeFieldWeapons()) { + totalCrewNeeded += requiredCrewForFieldWeapon((WeaponType) weapon.getType()); + if (totalCrewNeeded > activeTroopers) { weapon.setHit(true); } } @@ -976,14 +793,12 @@ protected void damageFieldGunsAndArty() { * for any place where damage can be assigned and removed without cost (lobby). Only affects Conventional Infantry, * not BattleArmor (can be called safely on BA). */ - public void damageOrRestoreFieldGunsAndArty() { + public void damageOrRestoreFieldWeapons() { int totalCrewNeeded = 0; - for (Mounted weapon : weaponList) { - if ((weapon.getLocation() == LOC_FIELD_GUNS) && (weapon.getType() instanceof WeaponType)) { - totalCrewNeeded += requiredCrewForFieldGun((WeaponType) weapon.getType()); - weapon.setHit(totalCrewNeeded > men); - weapon.setDestroyed(totalCrewNeeded > men); - } + for (Mounted weapon : originalFieldWeapons()) { + totalCrewNeeded += requiredCrewForFieldWeapon((WeaponType) weapon.getType()); + weapon.setHit(totalCrewNeeded > activeTroopers); + weapon.setDestroyed(totalCrewNeeded > activeTroopers); } } @@ -991,46 +806,50 @@ public void damageOrRestoreFieldGunsAndArty() { * @return The crew required to operate the given field gun or field artillery weapon, TO:AUE p.123. * The rules are silent on rounding for the weight of artillery, therefore adopting that of field guns. */ - public int requiredCrewForFieldGun(WeaponType weaponType) { + public int requiredCrewForFieldWeapon(WeaponType weaponType) { int roundedWeight = (int) Math.ceil(weaponType.getTonnage(this)); return weaponType.hasFlag(WeaponType.F_ARTILLERY) ? roundedWeight : Math.max(2, roundedWeight); } - /** - * Get the number of men in the platoon (before damage is applied). - */ + /** @return Active field guns and artillery of this infantry (= not including destroyed ones). Empty on BA. */ + public List activeFieldWeapons() { + return originalFieldWeapons().stream().filter(e -> !e.isDestroyed()).collect(toList()); + } + + /** @return All field guns and artillery of this infantry including destroyed ones. Empty on BA. */ + public List originalFieldWeapons() { + return getEquipment().stream().filter(this::isFieldWeapon).collect(toList()); + } + + /** @return True when the given Mounted is a Field Gun or Artillery. On BA, always returns false. */ + protected boolean isFieldWeapon(Mounted equipment) { + return (equipment.getType() instanceof WeaponType) && (equipment.getLocation() == LOC_FIELD_GUNS); + } + + /** @return The number of troopers in the platoon before damage of the current phase is applied. */ public int getShootingStrength() { - return menShooting; + return troopersShooting; } @Override public boolean canCharge() { - // Infantry can't Charge return false; } @Override public boolean canDFA() { - // Infantry can't DFA return false; } - /** - * Checks if the entity is moving into a swamp. If so, returns the target - * roll for the piloting skill check. now includes the level 3 terains which - * can bog down - */ @Override - public PilotingRollData checkBogDown(MoveStep step, - EntityMovementType moveType, Hex curHex, Coords lastPos, + public PilotingRollData checkBogDown(MoveStep step, EntityMovementType moveType, Hex curHex, Coords lastPos, Coords curPos, int lastElev, boolean isPavementStep) { return checkBogDown(step, curHex, lastPos, curPos, isPavementStep); } public PilotingRollData checkBogDown(MoveStep step, Hex curHex, Coords lastPos, Coords curPos, boolean isPavementStep) { - PilotingRollData roll = new PilotingRollData(getId(), 4, - "entering boggy terrain"); + PilotingRollData roll = new PilotingRollData(getId(), 4, "entering boggy terrain"); int bgMod = curHex.getBogDownModifier(getMovementMode(), false); final boolean onBridge = (curHex.terrainLevel(Terrains.BRIDGE) > 0) && (getElevation() == curHex.terrainLevel(Terrains.BRIDGE_ELEV)); @@ -1040,12 +859,10 @@ public PilotingRollData checkBogDown(MoveStep step, Hex curHex, && (getMovementMode() != EntityMovementMode.VTOL) && (getMovementMode() != EntityMovementMode.WIGE) && (step.getElevation() == 0) && !isPavementStep && !onBridge) { - roll.append(new PilotingRollData(getId(), bgMod, - "avoid bogging down")); + roll.append(new PilotingRollData(getId(), bgMod, "avoid bogging down")); } else { roll.addModifier(TargetRoll.CHECK_FALSE, - "Check false: Not entering bog-down terrain, " - + "or jumping/hovering over such terrain"); + "Check false: Not entering bog-down terrain, or jumping/hovering over such terrain"); } return roll; } @@ -1083,21 +900,14 @@ public double getPriceMultiplier() { priceMultiplier *= 2.6; break; case HOVER: - priceMultiplier *= 3.2; - break; case WHEELED: - priceMultiplier *= 3.2; - break; case TRACKED: + case SUBMARINE: // No cost given in TacOps, using basic mechanized cost for now priceMultiplier *= 3.2; break; case VTOL: priceMultiplier *= hasMicrolite() ? 4 : 4.5; break; - case SUBMARINE: - // No cost given in TacOps, using basic mechanized cost for now - priceMultiplier *= 3.2; - break; default: break; } @@ -1130,13 +940,13 @@ public double getPriceMultiplier() { @Override public double getAlternateCost() { double cost = 0; - if (null != primaryW) { - cost += primaryW.getCost(this, false, -1) * (squadsize - secondn); + if (null != primaryWeapon) { + cost += primaryWeapon.getCost(this, false, -1) * (squadSize - secondaryWeaponsPerSquad); } - if (null != secondW) { - cost += secondW.getCost(this, false, -1) * secondn; + if (null != secondaryWeapon) { + cost += secondaryWeapon.getCost(this, false, -1) * secondaryWeaponsPerSquad; } - cost = cost / squadsize; + cost = cost / squadSize; EquipmentType armor = getArmorKit(); if (armor != null) { @@ -1151,8 +961,6 @@ public double getAlternateCost() { cost += 17888 * 0.5; } break; - case INF_LEG: - break; case INF_MOTORIZED: cost += 17888 * 0.6; break; @@ -1171,13 +979,9 @@ public double getAlternateCost() { default: break; } - cost *= menStarting; + cost *= originalTrooperCount; // add in field gun costs - for (Mounted mounted : getEquipment()) { - if (mounted.getLocation() == LOC_FIELD_GUNS) { - cost += mounted.getType().getCost(this, false, -1); - } - } + cost += originalFieldWeapons().stream().mapToDouble(m -> m.getType().getCost(this, false, -1)).sum(); return cost; } @@ -1202,11 +1006,7 @@ public boolean doomedInExtremeTemp() { @Override public boolean doomedInVacuum() { - if (getMovementMode() == EntityMovementMode.VTOL) { - return true; - } else { - return !hasSpaceSuit(); - } + return getMovementMode().isVTOL() || !hasSpaceSuit(); } @Override @@ -1224,7 +1024,6 @@ public boolean doomedInSpace() { return true; } - @Override public boolean canAssaultDrop() { return game.getOptions().booleanOption(OptionsConstants.ADVANCED_PARATROOPERS); @@ -1243,10 +1042,9 @@ public boolean isEligibleFor(GamePhase phase) { @Override public boolean isEligibleForFiring() { - if (game.getOptions().booleanOption(OptionsConstants.ADVGRNDMOV_TACOPS_FAST_INFANTRY_MOVE)) { - if (moved == EntityMovementType.MOVE_RUN) { - return false; - } + if (game.getOptions().booleanOption(OptionsConstants.ADVGRNDMOV_TACOPS_FAST_INFANTRY_MOVE) + && (moved == EntityMovementType.MOVE_RUN)) { + return false; } return super.isEligibleForFiring(); } @@ -1255,7 +1053,7 @@ public boolean isEligibleForFiring() { public void newRound(int roundNumber) { if (turnsLayingExplosives >= 0) { turnsLayingExplosives++; - if (!(Compute.isInBuilding(game, this))) { + if (!Compute.isInBuilding(game, this)) { turnsLayingExplosives = -1; // give up if no longer in a building } } @@ -1288,11 +1086,10 @@ public boolean isNuclearHardened() { * overridden to ensure infantry are no longer considered dug in when they * are being transported. * - * @param transportID + * @param transportID The entity ID of the transporter */ public void setTransportID(int transportID) { super.setTransportId(transportID); - setDugIn(DUG_IN_NONE); } @@ -1302,15 +1099,14 @@ public void setTransportID(int transportID) { * anti-mek skill is set to the default untrained value, otherwise it's * set to the default value based on motive type. * - * @param amTraining + * @param amTraining True when the platoon is anti-mek trained */ public void setAntiMekSkill(boolean amTraining) { if (getCrew() == null) { return; } if (amTraining) { - if ((getMovementMode() == EntityMovementMode.INF_MOTORIZED) - || getMovementMode() == EntityMovementMode.INF_JUMP) { + if ((getMovementMode().isMotorizedInfantry()) || getMovementMode().isJumpInfantry()) { getCrew().setPiloting(ANTI_MECH_SKILL_JUMP, 0); } else { getCrew().setPiloting(ANTI_MECH_SKILL_FOOT, 0); @@ -1324,13 +1120,12 @@ public void setAntiMekSkill(boolean amTraining) { * Set the anti-mek skill for this unit. Since Infantry don't have piloting * the crew's piloting skill is treated as the anti-mek skill. This is * largely just a convenience method for setting the Crew's piloting skill. - * @param amSkill + * @param amSkill The new Anti-Mek skill */ public void setAntiMekSkill(int amSkill) { - if (getCrew() == null) { - return; + if (getCrew() != null) { + getCrew().setPiloting(amSkill, 0); } - getCrew().setPiloting(amSkill, 0); } /** @@ -1338,14 +1133,10 @@ public void setAntiMekSkill(int amSkill) { * piloting the crew's piloting skill is treated as the anti-mek skill. * This is largely just a convenience method for setting the Crew's piloting * skill. - * @return + * @return The Anti-Mek skill */ public int getAntiMekSkill() { - if (getCrew() == null) { - return ANTI_MECH_SKILL_UNTRAINED; - } else { - return getCrew().getPiloting(); - } + return (getCrew() == null) ? ANTI_MECH_SKILL_UNTRAINED : getCrew().getPiloting(); } /** @@ -1354,7 +1145,7 @@ public int getAntiMekSkill() { * training. This implies that the unit carries the requisite equipment for * properly performing anti-mek attacks (and the weight and cost that goes * along with that). - * @return + * @return True when this infantry is Anti-Mek trained */ public boolean isAntiMekTrained() { // Anything below the antimech skill default is considered to be AM @@ -1363,41 +1154,29 @@ public boolean isAntiMekTrained() { } public boolean isMechanized() { - return (getMovementMode() == EntityMovementMode.WHEELED) || - (getMovementMode() == EntityMovementMode.HOVER) || - (getMovementMode() == EntityMovementMode.TRACKED) || - (getMovementMode() == EntityMovementMode.SUBMARINE) || - (getMovementMode() == EntityMovementMode.VTOL); + return (getMovementMode().isTrackedWheeledOrHover()) || (getMovementMode().isSubmarine()) + || (getMovementMode().isVTOL()); } public boolean isXCT() { return hasSpecialization(XCT); } - /* - * (non-Javadoc) - * @see megamek.common.Entity#getTotalCommGearTons() - */ @Override public int getTotalCommGearTons() { return 0; } public EquipmentType getArmorKit() { - Optional kit = getEquipment().stream() + return getEquipment().stream() .filter(m -> m.getType().hasFlag(MiscType.F_ARMOR_KIT)) - .findFirst(); - if (kit.isPresent()) { - return kit.get().getType(); - } else { - return null; - } + .findFirst().map(Mounted::getType).orElse(null); } public void setArmorKit(EquipmentType armorKit) { List toRemove = getEquipment().stream() .filter(m -> m.getType().hasFlag(MiscType.F_ARMOR_KIT)) - .collect(Collectors.toList()); + .collect(toList()); getEquipment().removeAll(toRemove); getMisc().removeAll(toRemove); if (armorKit != null && armorKit.hasFlag(MiscType.F_ARMOR_KIT)) { @@ -1480,20 +1259,18 @@ public int getSpecializations() { public void setSpecializations(int spec) { // Equipment for Trench/Fieldworks Engineers if ((spec & TRENCH_ENGINEERS) > 0 && (infSpecs & TRENCH_ENGINEERS) == 0) { - // Need to add vibro shovels + // Add vibro shovels try { EquipmentType shovels = EquipmentType.get(EquipmentTypeLookup.VIBRO_SHOVEL); addEquipment(shovels, Infantry.LOC_INFANTRY); } catch (Exception e) { LogManager.getLogger().error("", e); } - } else if ((spec & TRENCH_ENGINEERS) == 0 - && (infSpecs & TRENCH_ENGINEERS) > 0) { + } else if ((spec & TRENCH_ENGINEERS) == 0 && (infSpecs & TRENCH_ENGINEERS) > 0) { // Need to remove vibro shovels List eqToRemove = new ArrayList<>(); for (Mounted eq : getEquipment()) { - if (eq.getType().hasFlag(MiscType.F_TOOLS) - && eq.getType().hasSubType(MiscType.S_VIBROSHOVEL)) { + if (eq.getType().hasFlag(MiscType.F_TOOLS) && eq.getType().hasSubType(MiscType.S_VIBROSHOVEL)) { eqToRemove.add(eq); } } @@ -1502,21 +1279,18 @@ public void setSpecializations(int spec) { } // Equipment for Demolition Engineers if ((spec & DEMO_ENGINEERS) > 0 && (infSpecs & DEMO_ENGINEERS) == 0) { - // Need to add vibro shovels + // Add demolition charge try { - EquipmentType shovels = EquipmentType.get(EquipmentTypeLookup.DEMOLITION_CHARGE); - addEquipment(shovels, Infantry.LOC_INFANTRY); + EquipmentType charge = EquipmentType.get(EquipmentTypeLookup.DEMOLITION_CHARGE); + addEquipment(charge, Infantry.LOC_INFANTRY); } catch (Exception e) { LogManager.getLogger().error("", e); } - } else if ((spec & DEMO_ENGINEERS) == 0 - && (infSpecs & DEMO_ENGINEERS) > 0) { + } else if ((spec & DEMO_ENGINEERS) == 0 && (infSpecs & DEMO_ENGINEERS) > 0) { // Need to remove vibro shovels List eqToRemove = new ArrayList<>(); for (Mounted eq : getEquipment()) { - if (eq.getType().hasFlag(MiscType.F_TOOLS) - && eq.getType() - .hasSubType(MiscType.S_DEMOLITION_CHARGE)) { + if (eq.getType().hasFlag(MiscType.F_TOOLS) && eq.getType().hasSubType(MiscType.S_DEMOLITION_CHARGE)) { eqToRemove.add(eq); } } @@ -1580,28 +1354,12 @@ public void setSneakECM(boolean b) { sneak_ecm = b; } - /** - * Determine the stealth modifier for firing at this unit from the given - * range. If the value supplied for range is not one of the - * Entity class range constants, an - * IllegalArgumentException will be thrown.

Sub-classes - * are encouraged to override this method. - * - * @param range - an int value that must match one of the - * Compute class range constants. - * @param ae - the entity making the attack. - * @return a TargetRoll value that contains the stealth - * modifier for the given range. - */ @Override public TargetRoll getStealthModifier(int range, Entity ae) { TargetRoll result = null; - // Note: infantry are immune to stealth, but not camoflage - // or mimetic armor - - if ((sneak_ir || dest) - && !(ae instanceof Infantry)) { + // Note: infantry are immune to stealth, but not camoflage or mimetic armor + if ((sneak_ir || dest) && !(ae instanceof Infantry)) { switch (range) { case RangeType.RANGE_MINIMUM: case RangeType.RANGE_SHORT: @@ -1616,8 +1374,7 @@ public TargetRoll getStealthModifier(int range, Entity ae) { case RangeType.RANGE_OUT: break; default: - throw new IllegalArgumentException( - "Unknown range constant: " + range); + throw new IllegalArgumentException("Unknown range constant: " + range); } } @@ -1640,52 +1397,45 @@ public TargetRoll getStealthModifier(int range, Entity ae) { } } - if (result == null) { result = new TargetRoll(0, "no sneak mods"); } - // Return the result. return result; - } // End public TargetRoll getStealthModifier( char ) + } - /** - * Determines if the infantry has any type of stealth system. - * - * @return - */ + /** @return True if this infantry has any type of stealth system. */ public boolean isStealthy() { - return dest || sneak_camo || sneak_ir || sneak_ecm; + return dest || sneak_camo || sneak_ir || sneak_ecm; } public boolean hasMicrolite() { - return microlite; + return isMicrolite; } public void setMicrolite(boolean microlite) { - this.microlite = microlite; + this.isMicrolite = microlite; } /** - * Used to check for standard or motorized SCUBA infantry, which have a maximum - * depth of 2. + * Used to check for standard or motorized SCUBA infantry, which have a maximum depth of 2. * @return true if this is a conventional infantry unit with non-mechanized SCUBA specialization */ public boolean isNonMechSCUBA() { - return isConventionalInfantry() && (getMovementMode() == EntityMovementMode.INF_UMU); + return isConventionalInfantry() && getMovementMode().isUMUInfantry(); } public void setPrimaryWeapon(InfantryWeapon w) { - primaryW = w; + primaryWeapon = w; primaryName = w.getName(); } public InfantryWeapon getPrimaryWeapon() { - return primaryW; + return primaryWeapon; } public void setSecondaryWeapon(InfantryWeapon w) { - secondW = w; + secondaryWeapon = w; if (null == w) { secondName = null; } else { @@ -1694,45 +1444,45 @@ public void setSecondaryWeapon(InfantryWeapon w) { } public InfantryWeapon getSecondaryWeapon() { - return secondW; + return secondaryWeapon; } public void setSquadSize(int size) { - squadsize = size; + squadSize = size; } public int getSquadSize() { - return squadsize; + return squadSize; } - public void setSquadN(int n) { - squadn = n; + public void setSquadCount(int n) { + squadCount = n; } - public int getSquadN() { - return squadn; + public int getSquadCount() { + return squadCount; } - public void setSecondaryN(int n) { - secondn = n; + public void setSecondaryWeaponsPerSquad(int n) { + secondaryWeaponsPerSquad = n; } - public int getSecondaryN() { - return secondn; + public int getSecondaryWeaponsPerSquad() { + return secondaryWeaponsPerSquad; } public double getDamagePerTrooper() { - if (null == primaryW) { + if (null == primaryWeapon) { return 0; } // per 09/2021 errata, primary infantry weapon damage caps out at 0.6 - double adjustedDamage = Math.min(MMConstants.INFANTRY_PRIMARY_WEAPON_DAMAGE_CAP, primaryW.getInfantryDamage()); - double damage = adjustedDamage * (squadsize - secondn); - if (null != secondW) { - damage += secondW.getInfantryDamage() * secondn; + double adjustedDamage = Math.min(MMConstants.INFANTRY_PRIMARY_WEAPON_DAMAGE_CAP, primaryWeapon.getInfantryDamage()); + double damage = adjustedDamage * (squadSize - secondaryWeaponsPerSquad); + if (null != secondaryWeapon) { + damage += secondaryWeapon.getInfantryDamage() * secondaryWeaponsPerSquad; } - return damage/squadsize; + return damage / squadSize; } public boolean primaryWeaponDamageCapped() { @@ -1740,20 +1490,13 @@ public boolean primaryWeaponDamageCapped() { } public double getPrimaryWeaponDamage() { - if (null == primaryW) { - return 0; - } - - return primaryW.getInfantryDamage(); + return (primaryWeapon != null) ? primaryWeapon.getInfantryDamage() : 0; } public boolean isSquad() { - return (squadn == 1); + return squadCount == 1; } - /** - * Set the movement type of the entity - */ @Override public void setMovementMode(EntityMovementMode movementMode) { super.setMovementMode(movementMode); @@ -1762,14 +1505,12 @@ public void setMovementMode(EntityMovementMode movementMode) { setOriginalJumpMP(0); switch (getMovementMode()) { case INF_MOTORIZED: + case TRACKED: setOriginalWalkMP(3); break; case HOVER: setOriginalWalkMP(5); break; - case TRACKED: - setOriginalWalkMP(3); - break; case WHEELED: setOriginalWalkMP(4); break; @@ -1806,8 +1547,7 @@ public void setMovementMode(EntityMovementMode movementMode) { /** * Standard and motorized SCUBA only differ in base movement, so they both use - * INF_UMU. If the motion_type contains the string "motorized", - * the movement is set here instead. + * INF_UMU. If the motion_type contains the string "motorized", the movement is set here instead. */ public void setMotorizedScuba() { setMovementMode(EntityMovementMode.INF_UMU); @@ -1817,10 +1557,10 @@ public void setMotorizedScuba() { @Override public String getMovementModeAsString() { if (!hasETypeFlag(Entity.ETYPE_BATTLEARMOR)) { - if (getMovementMode().equals(EntityMovementMode.VTOL)) { + if (getMovementMode().isVTOL()) { return hasMicrolite() ? "Microlite" : "Microcopter"; } - if (getMovementMode() == EntityMovementMode.INF_UMU) { + if (getMovementMode().isUMUInfantry()) { return getOriginalJumpMP() > 1 ? "Motorized SCUBA" : "SCUBA"; } } @@ -1834,7 +1574,7 @@ public String getMovementModeAsString() { * but has a fixed 8 AM skill rating. */ public boolean canMakeAntiMekAttacks() { - return !isMechanized() && !isArmorEncumbering() && !hasActiveFieldGun(); + return !isMechanized() && !isArmorEncumbering() && !hasActiveFieldWeapon(); } @Override @@ -1850,16 +1590,16 @@ public double getWeight() { mult = 1.0; break; case VTOL: - mult = (hasMicrolite() ? 1.4 : 1.9); + mult = hasMicrolite() ? 1.4 : 1.9; break; case INF_JUMP: mult = 0.165; break; case INF_UMU: if (getActiveUMUCount() > 1) { - mult = 0.295; //motorized + 0.1 for motorized scuba + mult = 0.295; // motorized + 0.1 for motorized scuba } else { - mult = 0.135; //foot + 0.05 for scuba + mult = 0.135; // foot + 0.05 for scuba } break; case SUBMARINE: @@ -1886,14 +1626,8 @@ public double getWeight() { mult +=.015; } - double ton = men * mult; - - // Add field gun weight - ton += getEquipment().stream() - .filter(e -> e.getLocation() == LOC_FIELD_GUNS) - .filter(e -> !e.isDestroyed()) - .mapToDouble(Mounted::getTonnage).sum(); - + double ton = activeTroopers * mult; + ton += activeFieldWeapons().stream().mapToDouble(Mounted::getTonnage).sum(); return RoundWeight.nearestHalfTon(ton); } @@ -1912,9 +1646,7 @@ public String getArmorDesc() { sArmor.append(" (DEST) "); } - if (hasSneakCamo() || - (getCrew() != null - && hasAbility(OptionsConstants.MD_DERMAL_CAMO_ARMOR))) { + if (hasSneakCamo() || (getCrew() != null && hasAbility(OptionsConstants.MD_DERMAL_CAMO_ARMOR))) { sArmor.append(" (Camo) "); } @@ -1929,33 +1661,26 @@ && hasAbility(OptionsConstants.MD_DERMAL_CAMO_ARMOR))) { return sArmor.toString(); } - /** - * Restores the entity after serialization - */ @Override public void restore() { super.restore(); if (null != primaryName) { - primaryW = (InfantryWeapon) EquipmentType.get(primaryName); + primaryWeapon = (InfantryWeapon) EquipmentType.get(primaryName); } if (null != secondName) { - secondW = (InfantryWeapon) EquipmentType.get(secondName); + secondaryWeapon = (InfantryWeapon) EquipmentType.get(secondName); } } /** @return True if this infantry has a field artillery weapon that is not destroyed. */ public boolean hasActiveFieldArtillery() { - return getWeaponList().stream() - .filter(weapon -> weapon.getLocation() == LOC_FIELD_GUNS) - .filter(weapon -> weapon.getType().hasFlag(WeaponType.F_ARTILLERY)) - .anyMatch(weapon -> !weapon.isDestroyed()); + return activeFieldWeapons().stream().anyMatch(gun -> gun.getType().hasFlag(WeaponType.F_ARTILLERY)); } /** - * Infantry don't use MP to change facing, and don't - * do PSRs, so just don't let them use maneuvering ace + * Infantry don't use MP to change facing, and don't do PSRs, so just don't let them use maneuvering ace * otherwise, their movement gets screwed up */ @Override @@ -2005,14 +1730,14 @@ public boolean isDmgLight() { return (((double) getInternal(LOC_INFANTRY) / getOInternal(LOC_INFANTRY)) < 0.9); } - /** @return True if this infantry has any field gun (destroyed or not). */ - public boolean hasFieldGun() { - return getWeaponList().stream().anyMatch(m -> m.getLocation() == LOC_FIELD_GUNS); + /** @return True if this infantry has any field gun or artillery (destroyed or not). */ + public boolean hasFieldWeapon() { + return !originalFieldWeapons().isEmpty(); } - /** @return True if this infantry has any working (not destroyed) field gun. */ - public boolean hasActiveFieldGun() { - return getWeaponList().stream().filter(m -> !m.isDestroyed()).anyMatch(m -> m.getLocation() == LOC_FIELD_GUNS); + /** @return True if this infantry has any working (not destroyed) field gun or artillery. */ + public boolean hasActiveFieldWeapon() { + return !activeFieldWeapons().isEmpty(); } @Override @@ -2020,18 +1745,11 @@ public boolean hasEngine() { return false; } - /** - * Mounts the specified equipment in the specified location. - */ @Override public void addEquipment(Mounted mounted, int loc, boolean rearMounted) throws LocationFullException { - // Implement parent's behavior. super.addEquipment(mounted, loc, rearMounted); - - //we do need to equipment slots for ammo switching of field guns and field artillery - // Add the piece equipment to our slots. + // Add equipment slots for ammo switching of field guns and field artillery addCritical(loc, new CriticalSlot(mounted)); - } @Override @@ -2045,11 +1763,9 @@ public long getEntityType() { } @Override - public PilotingRollData checkLandingInHeavyWoods( - EntityMovementType overallMoveType, Hex curHex) { + public PilotingRollData checkLandingInHeavyWoods(EntityMovementType overallMoveType, Hex curHex) { PilotingRollData roll = getBasePilotingRoll(overallMoveType); - roll.addModifier(TargetRoll.CHECK_FALSE, - "Infantry cannot fall"); + roll.addModifier(TargetRoll.CHECK_FALSE, "Infantry cannot fall"); return roll; } @@ -2057,9 +1773,9 @@ public PilotingRollData checkLandingInHeavyWoods( * Determines if there is valid cover for an infantry unit to utilize the * Using Non-Infantry as Cover rules (TO pg 108). * @param game The current {@link Game} - * @param pos - * @param elevation - * @return + * @param pos The hex coords + * @param elevation The elevation (flying or in building) + * @return True when this infantry has valid conver */ public static boolean hasValidCover(Game game, Coords pos, int elevation) { // Can't do anything if we don't have a position @@ -2071,8 +1787,7 @@ public static boolean hasValidCover(Game game, Coords pos, int elevation) { boolean hasMovedEntity = false; // First, look for ground untis in the same hex that have already moved for (Entity e : game.getEntitiesVector(pos)) { - if (e.isDone() && !(e instanceof Infantry) - && (e.getElevation() == elevation)) { + if (e.isDone() && !(e instanceof Infantry) && (e.getElevation() == elevation)) { hasMovedEntity = true; break; } @@ -2083,8 +1798,7 @@ public static boolean hasValidCover(Game game, Coords pos, int elevation) { Enumeration wrecks = game.getWreckedEntities(); while (wrecks.hasMoreElements()) { Entity e = wrecks.nextElement(); - if (pos.equals(e.getPosition()) - && !(e instanceof Infantry)) { + if (pos.equals(e.getPosition()) && !(e instanceof Infantry)) { hasMovedEntity = true; } } @@ -2105,15 +1819,8 @@ protected boolean hasViableWeapons() { return !isCrippled(); } - /** - * Used to determine the draw priority of different Entity subclasses. - * This allows different unit types to always be draw above/below other - * types. - * - * @return - */ @Override public int getSpriteDrawPriority() { return 1; } -} // End class Infantry +} \ No newline at end of file diff --git a/megamek/src/megamek/common/InfantryBay.java b/megamek/src/megamek/common/InfantryBay.java index 8a013694225..08ed23ea448 100644 --- a/megamek/src/megamek/common/InfantryBay.java +++ b/megamek/src/megamek/common/InfantryBay.java @@ -112,7 +112,7 @@ public InfantryBay(double space, int doors, int bayNumber, PlatoonType bayType) public double spaceForUnit(Entity unit) { PlatoonType type = PlatoonType.getPlatoonType(unit); if ((unit instanceof Infantry) && (type == PlatoonType.MECHANIZED)) { - return type.getWeight() * ((Infantry) unit).getSquadN(); + return type.getWeight() * ((Infantry) unit).getSquadCount(); } else { return type.getWeight(); } diff --git a/megamek/src/megamek/common/MULParser.java b/megamek/src/megamek/common/MULParser.java index 17a01cd52bb..2e45a4c3156 100644 --- a/megamek/src/megamek/common/MULParser.java +++ b/megamek/src/megamek/common/MULParser.java @@ -827,7 +827,7 @@ private void parseEntityAttributes(Entity entity, Element entityTag) { String infSquadNum = entityTag.getAttribute(INF_SQUAD_NUM); if (!infSquadNum.isBlank()) { - inf.setSquadN(Integer.parseInt(infSquadNum)); + inf.setSquadCount(Integer.parseInt(infSquadNum)); inf.autoSetInternal(); } } @@ -1455,7 +1455,7 @@ private void parseArmor(Element armorTag, Entity entity, int loc) { } else { entity.setInternal(pointsVal, loc); if (entity instanceof Infantry) { - ((Infantry) entity).damageOrRestoreFieldGunsAndArty(); + ((Infantry) entity).damageOrRestoreFieldWeapons(); entity.applyDamage(); } } @@ -2690,7 +2690,7 @@ private void destroyLocation(Entity en, int loc) { en.setArmor(IArmorState.ARMOR_DESTROYED, loc, false); en.setInternal(IArmorState.ARMOR_DESTROYED, loc); if (en instanceof Infantry) { - ((Infantry) en).damageOrRestoreFieldGunsAndArty(); + ((Infantry) en).damageOrRestoreFieldWeapons(); en.applyDamage(); } if (en.hasRearArmor(loc)) { diff --git a/megamek/src/megamek/common/MechView.java b/megamek/src/megamek/common/MechView.java index defd7cb763d..f64c3b35493 100644 --- a/megamek/src/megamek/common/MechView.java +++ b/megamek/src/megamek/common/MechView.java @@ -561,7 +561,7 @@ private List getInternalAndArmor() { Infantry inf = (Infantry) entity; retVal.add(new LabeledElement(Messages.getString("MechView.Men"), entity.getTotalInternal() - + " (" + inf.getSquadSize() + "/" + inf.getSquadN() + + " (" + inf.getSquadSize() + "/" + inf.getSquadCount() + ")")); } else { String internal = String.valueOf(entity.getTotalInternal()); @@ -760,7 +760,7 @@ private List getWeapons(boolean showDetail) { retVal.add(new LabeledElement("Secondary Weapon", (null != inf.getSecondaryWeapon()) ? inf.getSecondaryWeapon().getDesc() - + " (" + inf.getSecondaryN() + ")" : "None")); + + " (" + inf.getSecondaryWeaponsPerSquad() + ")" : "None")); retVal.add(new LabeledElement("Damage per trooper", String.format("%3.3f", inf.getDamagePerTrooper()))); retVal.add(new SingleLine()); diff --git a/megamek/src/megamek/common/alphaStrike/conversion/ASConvInfantryDamageConverter.java b/megamek/src/megamek/common/alphaStrike/conversion/ASConvInfantryDamageConverter.java index 8ddeb9f386f..1bded9a80ed 100644 --- a/megamek/src/megamek/common/alphaStrike/conversion/ASConvInfantryDamageConverter.java +++ b/megamek/src/megamek/common/alphaStrike/conversion/ASConvInfantryDamageConverter.java @@ -45,7 +45,7 @@ protected void processDamage() { report.addEmptyLine(); report.addLine("--- Damage:", ""); int baseRange = 0; - if ((infantry.getSecondaryWeapon() != null) && (infantry.getSecondaryN() >= 2)) { + if ((infantry.getSecondaryWeapon() != null) && (infantry.getSecondaryWeaponsPerSquad() >= 2)) { baseRange = infantry.getSecondaryWeapon().getInfantryRange(); } else if (infantry.getPrimaryWeapon() != null) { baseRange = infantry.getPrimaryWeapon().getInfantryRange(); diff --git a/megamek/src/megamek/common/alphaStrike/conversion/ASLocationMapper.java b/megamek/src/megamek/common/alphaStrike/conversion/ASLocationMapper.java index a365d08dd94..66b6a353461 100644 --- a/megamek/src/megamek/common/alphaStrike/conversion/ASLocationMapper.java +++ b/megamek/src/megamek/common/alphaStrike/conversion/ASLocationMapper.java @@ -48,7 +48,7 @@ static int damageLocationsCount(Entity en) { } else if (en instanceof BattleArmor) { return 1; } else if (en instanceof Infantry) { - return ((Infantry) en).hasFieldGun() ? 2 : 1; + return ((Infantry) en).hasFieldWeapon() ? 2 : 1; } else { return 1; } diff --git a/megamek/src/megamek/common/battlevalue/InfantryBVCalculator.java b/megamek/src/megamek/common/battlevalue/InfantryBVCalculator.java index 8251e99b08d..9f4b176cef4 100644 --- a/megamek/src/megamek/common/battlevalue/InfantryBVCalculator.java +++ b/megamek/src/megamek/common/battlevalue/InfantryBVCalculator.java @@ -94,8 +94,8 @@ public static int calculateBV(Infantry infantry, boolean ignoreSkill, Calculatio InfantryWeapon primaryW = infantry.getPrimaryWeapon(); InfantryWeapon secondW = infantry.getSecondaryWeapon(); int squadsize = infantry.getSquadSize(); - int secondn = infantry.getSecondaryN(); - int squadn = infantry.getSquadN(); + int secondn = infantry.getSecondaryWeaponsPerSquad(); + int squadn = infantry.getSquadCount(); if (null != primaryW) { wbv += primaryW.getBV(infantry) * (squadsize - secondn); diff --git a/megamek/src/megamek/common/cost/InfantryCostCalculator.java b/megamek/src/megamek/common/cost/InfantryCostCalculator.java index 498876518de..b0d27da9383 100644 --- a/megamek/src/megamek/common/cost/InfantryCostCalculator.java +++ b/megamek/src/megamek/common/cost/InfantryCostCalculator.java @@ -21,7 +21,6 @@ import megamek.client.ui.swing.calculationReport.CalculationReport; import megamek.common.EquipmentType; import megamek.common.Infantry; -import megamek.common.Mounted; public class InfantryCostCalculator { @@ -40,7 +39,7 @@ public static double calculateCost(Infantry infantry, CalculationReport costRepo } // Determining Break down of who would have primary and secondary weapons. - double primarySquad = (infantry.getSquadSize() - infantry.getSecondaryN()) * infantry.getSquadN(); + double primarySquad = (infantry.getSquadSize() - infantry.getSecondaryWeaponsPerSquad()) * infantry.getSquadCount(); double secondSquad = infantry.getOInternal(0) - primarySquad; // OInternal = menStarting // Squad Cost with just the weapons. @@ -93,13 +92,9 @@ public static double calculateCost(Infantry infantry, CalculationReport costRepo costs[idx++] = -infantry.getPriceMultiplier(); // add in field gun costs - double fieldGunCost = 0; - for (Mounted mounted : infantry.getEquipment()) { - if (mounted.getLocation() == Infantry.LOC_FIELD_GUNS) { - fieldGunCost += Math.floor(mounted.getType().getCost(infantry, false, mounted.getLocation())); - } - } - costs[idx] = fieldGunCost; + costs[idx] = infantry.originalFieldWeapons().stream() + .mapToDouble(m -> m.getType().getCost(infantry, false, m.getLocation())).sum(); + double cost = CostCalculator.calculateCost(costs); String[] systemNames = { "Weapons", "Armor", "Multiplier", "Field Gun" }; CostCalculator.fillInReport(costReport, infantry, ignoreAmmo, systemNames, -1, cost, costs); diff --git a/megamek/src/megamek/common/loaders/BLKFile.java b/megamek/src/megamek/common/loaders/BLKFile.java index c6c5cd91a24..31cd5c85755 100644 --- a/megamek/src/megamek/common/loaders/BLKFile.java +++ b/megamek/src/megamek/common/loaders/BLKFile.java @@ -878,9 +878,9 @@ public static BuildingBlock getBlock(Entity t) { } else if (t instanceof Infantry) { Infantry infantry = (Infantry) t; blk.writeBlockData("squad_size", infantry.getSquadSize()); - blk.writeBlockData("squadn", infantry.getSquadN()); - if (infantry.getSecondaryN() > 0) { - blk.writeBlockData("secondn", infantry.getSecondaryN()); + blk.writeBlockData("squadn", infantry.getSquadCount()); + if (infantry.getSecondaryWeaponsPerSquad() > 0) { + blk.writeBlockData("secondn", infantry.getSecondaryWeaponsPerSquad()); } if (null != infantry.getPrimaryWeapon()) { blk.writeBlockData("Primary", infantry.getPrimaryWeapon() diff --git a/megamek/src/megamek/common/loaders/BLKInfantryFile.java b/megamek/src/megamek/common/loaders/BLKInfantryFile.java index ec3f0eca98b..9db1a166463 100644 --- a/megamek/src/megamek/common/loaders/BLKInfantryFile.java +++ b/megamek/src/megamek/common/loaders/BLKInfantryFile.java @@ -68,7 +68,7 @@ public Entity getEntity() throws EntityLoadingException { if (!dataFile.exists("squadn")) { throw new EntityLoadingException("Could not find number of squads."); } - t.setSquadN(dataFile.getDataAsInt("squadn")[0]); + t.setSquadCount(dataFile.getDataAsInt("squadn")[0]); t.autoSetInternal(); @@ -94,7 +94,7 @@ public Entity getEntity() throws EntityLoadingException { // get primary and secondary weapons if (dataFile.exists("secondn")) { - t.setSecondaryN(dataFile.getDataAsInt("secondn")[0]); + t.setSecondaryWeaponsPerSquad(dataFile.getDataAsInt("secondn")[0]); } if (!dataFile.exists("Primary")) { @@ -120,7 +120,7 @@ public Entity getEntity() throws EntityLoadingException { // if there is more than one secondary weapon per squad, then add that // to the unit // otherwise add the primary weapon - if ((t.getSecondaryN() > 1) && (null != stype)) { + if ((t.getSecondaryWeaponsPerSquad() > 1) && (null != stype)) { try { t.addEquipment(stype, Infantry.LOC_INFANTRY); } catch (LocationFullException ex) { diff --git a/megamek/src/megamek/common/templates/InfantryTROView.java b/megamek/src/megamek/common/templates/InfantryTROView.java index 0e5e7c6d646..d5c806a3778 100644 --- a/megamek/src/megamek/common/templates/InfantryTROView.java +++ b/megamek/src/megamek/common/templates/InfantryTROView.java @@ -56,10 +56,10 @@ protected void initModel(EntityVerifier verifier) { addEntityFluff(inf); setModelData("transportWeight", inf.getWeight()); setModelData("weaponPrimary", String.format("%d %s", - (inf.getSquadSize() - inf.getSecondaryN()) * inf.getSquadN(), inf.getPrimaryWeapon().getName())); + (inf.getSquadSize() - inf.getSecondaryWeaponsPerSquad()) * inf.getSquadCount(), inf.getPrimaryWeapon().getName())); setModelData("weaponSecondary", (inf.getSecondaryWeapon() == null) ? Messages.getString("TROView.None") - : String.format("%d %s", inf.getSecondaryN() * inf.getSquadN(), inf.getSecondaryWeapon().getName())); + : String.format("%d %s", inf.getSecondaryWeaponsPerSquad() * inf.getSquadCount(), inf.getSecondaryWeapon().getName())); final EquipmentType armorKit = inf.getArmorKit(); if (null != armorKit) { setModelData("armorKit", armorKit.getName()); @@ -117,10 +117,10 @@ protected void initModel(EntityVerifier verifier) { setModelData("umuMP", inf.getOriginalJumpMP()); } setModelData("squadSize", inf.getSquadSize()); - setModelData("squadCount", inf.getSquadN()); + setModelData("squadCount", inf.getSquadCount()); setModelData("armorDivisor", inf.calcDamageDivisor()); InfantryWeapon rangeWeapon = inf.getPrimaryWeapon(); - if ((inf.getSecondaryN() > 1) && (inf.getSecondaryWeapon() != null)) { + if ((inf.getSecondaryWeaponsPerSquad() > 1) && (inf.getSecondaryWeapon() != null)) { rangeWeapon = inf.getSecondaryWeapon(); } @@ -179,7 +179,7 @@ private void addWeaponNotes(List notes) { notes.add(String.format(Messages.getString("TROView.InfantryNote.SingleFieldGun"), fieldGuns.get(0).getName(), shots, (int) fieldGuns.get(0).getTonnage(inf))); } - if ((inf.getSecondaryN() > 1) && (inf.getSecondaryWeapon() != null)) { + if ((inf.getSecondaryWeaponsPerSquad() > 1) && (inf.getSecondaryWeapon() != null)) { if (inf.getSecondaryWeapon().hasFlag(WeaponType.F_INF_BURST)) { notes.add(Messages.getString("TROView.InfantryNote.Burst")); } diff --git a/megamek/src/megamek/common/verifier/TestInfantry.java b/megamek/src/megamek/common/verifier/TestInfantry.java index 3930a1c6925..27719f314d9 100644 --- a/megamek/src/megamek/common/verifier/TestInfantry.java +++ b/megamek/src/megamek/common/verifier/TestInfantry.java @@ -130,7 +130,7 @@ public boolean correctEntity(StringBuffer buff, int ammoTechLvl) { } int max = maxSecondaryWeapons(inf); - if (inf.getSecondaryN() > max) { + if (inf.getSecondaryWeaponsPerSquad() > max) { buff.append("Number of secondary weapons exceeds maximum of " + max).append("\n\n"); correct = false; } @@ -146,7 +146,7 @@ public boolean correctEntity(StringBuffer buff, int ammoTechLvl) { } } secondaryCrew = Math.max(secondaryCrew, 1); - if (secondaryCrew * inf.getSecondaryN() > inf.getSquadSize()) { + if (secondaryCrew * inf.getSecondaryWeaponsPerSquad() > inf.getSquadSize()) { buff.append("Secondary weapon crew requirement exceeds squad size.").append("\n\n"); correct = false; } diff --git a/megamek/src/megamek/server/GameManager.java b/megamek/src/megamek/server/GameManager.java index 3e90c4a4a4e..6f97aeba0ea 100644 --- a/megamek/src/megamek/server/GameManager.java +++ b/megamek/src/megamek/server/GameManager.java @@ -32711,7 +32711,7 @@ public void resolveCallSupport() { Infantry guerrilla = new Infantry(); guerrilla.setChassis("Insurgents"); guerrilla.setModel("(Rifle)"); - guerrilla.setSquadN(4); + guerrilla.setSquadCount(4); guerrilla.setSquadSize(7); guerrilla.autoSetInternal(); guerrilla.getCrew().setGunnery(5, 0);