diff --git a/megamek/src/megamek/common/Entity.java b/megamek/src/megamek/common/Entity.java index 030ee89ec36..79f82cdaabf 100644 --- a/megamek/src/megamek/common/Entity.java +++ b/megamek/src/megamek/common/Entity.java @@ -3167,6 +3167,24 @@ public int getLocationFromAbbr(String abbr) { return Entity.LOC_NONE; } + /** + * Joins the abbreviations for the locations into a String with / as the separator. + * If the number of locations exceeds the provided limit, the result is + * abbreviated. By default the abbreviation is simply an asterisk, but Mechs have + * specific abbreviations locations that include all torso or leg positions. + * + * @param locations A list of location indices + * @param limit The maximum number of locations to show in full + * @return A string formatted for display that shows the locations + */ + public String joinLocationAbbr(List locations, int limit) { + if (locations.size() > limit) { + return "*"; + } else { + return locations.stream().map(l -> getLocationAbbr(l)).collect(Collectors.joining("/")); + } + } + /** * Rolls the to-hit number */ diff --git a/megamek/src/megamek/common/Mech.java b/megamek/src/megamek/common/Mech.java index efcb2f29da9..784a983e5ae 100644 --- a/megamek/src/megamek/common/Mech.java +++ b/megamek/src/megamek/common/Mech.java @@ -20,6 +20,7 @@ import java.math.BigInteger; import java.text.NumberFormat; import java.util.*; +import java.util.stream.Collectors; import megamek.MegaMek; import megamek.common.loaders.MtfFile; @@ -2098,6 +2099,18 @@ public boolean isSecondaryArcWeapon(int weaponId) { return true; } + @Override + public String joinLocationAbbr(List locations, int limit) { + // If all locations are torso, strip the T from all but the last location. + // e.g. R/L/CT + if ((locations.size() > limit) && locations.stream().allMatch(this::locationIsTorso)) { + return locations.stream().map(l -> getLocationAbbr(l).replace("T", "")) + .collect(Collectors.joining("/")) + "T"; + } else { + return super.joinLocationAbbr(locations, limit); + } + } + /* * (non-Javadoc) * diff --git a/megamek/src/megamek/common/MechView.java b/megamek/src/megamek/common/MechView.java index 9e36436517d..144d49c9900 100644 --- a/megamek/src/megamek/common/MechView.java +++ b/megamek/src/megamek/common/MechView.java @@ -777,8 +777,7 @@ private List getWeapons(boolean showDetail) { wpnTable.setJustification(TableElement.JUSTIFIED_LEFT, TableElement.JUSTIFIED_CENTER, TableElement.JUSTIFIED_CENTER, TableElement.JUSTIFIED_LEFT); for (Mounted mounted : entity.getWeaponList()) { - String[] row = new String[] { mounted.getDesc(), - entity.getLocationAbbr(mounted.getLocation()), "", "" }; + String[] row = { mounted.getDesc(), entity.joinLocationAbbr(mounted.allLocations(), 3), "", "" }; WeaponType wtype = (WeaponType) mounted.getType(); if (entity.isClan() @@ -796,11 +795,6 @@ private List getWeapons(boolean showDetail) { * //$NON-NLS-1$ } */ - if (mounted.isSplit()) { - row[1] += "/" + entity.getLocationAbbr(mounted // $NON-NLS-1$ - .getSecondLocation()); - } - int heat = wtype.getHeat(); int bWeapDamaged = 0; if (wtype instanceof BayWeapon) { @@ -912,7 +906,7 @@ private ViewElement getAmmo() { if (mounted.getLocation() == Entity.LOC_NONE) { continue; } - + String[] row = { mounted.getName(), entity.getLocationAbbr(mounted.getLocation()), String.valueOf(mounted.getBaseShotsLeft()), "" }; if (entity.isOmni()) { @@ -997,7 +991,7 @@ private List getMisc() { } nEquip++; - String[] row = { mounted.getDesc(), entity.getLocationAbbr(mounted.getLocation()), "" }; + String[] row = { mounted.getDesc(), entity.joinLocationAbbr(mounted.allLocations(), 3), "" }; if (entity.isClan() && (mounted.getType().getTechBase() == ITechnology.TECH_BASE_IS)) { row[0] += Messages.getString("MechView.IS"); //$NON-NLS-1$ diff --git a/megamek/src/megamek/common/Mounted.java b/megamek/src/megamek/common/Mounted.java index dc87cb6c1a8..4b011024928 100644 --- a/megamek/src/megamek/common/Mounted.java +++ b/megamek/src/megamek/common/Mounted.java @@ -22,10 +22,7 @@ package megamek.common; import java.io.Serializable; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.Vector; +import java.util.*; import megamek.MegaMek; import megamek.common.actions.WeaponAttackAction; @@ -1066,6 +1063,38 @@ public void setSecondLocation(int location, boolean rearMounted) { this.rearMounted = rearMounted; } + /** + * Fetches all locations that contain this equipment. This is primarily for + * spreadable equipment, can be placed in locations other than the primary or secondary, + * but will also work for non-spreadable equipment. + * + * @return A list of indices for all locations that contain this equipment. + * @see #getLocation() + * @see #getSecondLocation() + */ + public List allLocations() { + List locations = new ArrayList<>(); + if (getType().isSpreadable()) { + for (int loc = 0; loc < getEntity().locations(); loc++) { + for (int slot = 0; slot < getEntity().getNumberOfCriticals(loc); slot++) { + final CriticalSlot crit = getEntity().getCritical(loc, slot); + if ((crit != null) && ((crit.getMount() == this) || (crit.getMount2() == this))) { + locations.add(loc); + break; + } + } + } + } else { + if (getLocation() >= 0) { + locations.add(getLocation()); + } + if (getSecondLocation() >= 0) { + locations.add(getSecondLocation()); + } + } + return locations; + } + public Mounted getLinked() { return linked; } diff --git a/megamek/src/megamek/common/QuadMech.java b/megamek/src/megamek/common/QuadMech.java index 3821d33c4a2..7dbad102964 100644 --- a/megamek/src/megamek/common/QuadMech.java +++ b/megamek/src/megamek/common/QuadMech.java @@ -17,6 +17,7 @@ package megamek.common; import java.io.PrintWriter; +import java.util.List; import megamek.common.options.OptionsConstants; import megamek.common.preference.PreferenceManager; @@ -423,6 +424,16 @@ protected double getLegActuatorCost() { return (weight * 150 * 4) + (weight * 80 * 4) + (weight * 120 * 4); } + @Override + public String joinLocationAbbr(List locations, int limit) { + // If we need to abbreviate something that occupies all leg locations, simply return "Legs" + if ((locations.size() > limit) && (locations.size() == 4) && locations.stream().allMatch(this::locationIsLeg)) { + return "Legs"; + } else { + return super.joinLocationAbbr(locations, limit); + } + } + @Override public HitData rollHitLocation(int table, int side, int aimedLocation, int aimingMode, int cover) { int roll = -1; diff --git a/megamek/src/megamek/common/TripodMech.java b/megamek/src/megamek/common/TripodMech.java index a3f5b4d972d..72b511075a4 100644 --- a/megamek/src/megamek/common/TripodMech.java +++ b/megamek/src/megamek/common/TripodMech.java @@ -16,6 +16,7 @@ package megamek.common; import java.io.PrintWriter; +import java.util.List; import megamek.common.options.OptionsConstants; import megamek.common.preference.PreferenceManager; @@ -979,6 +980,16 @@ public int locations() { return 9; } + @Override + public String joinLocationAbbr(List locations, int limit) { + // If we need to abbreviate something that occupies all leg locations, simply return "Legs" + if ((locations.size() > limit) && (locations.size() == 3) && locations.stream().allMatch(this::locationIsLeg)) { + return "Legs"; + } else { + return super.joinLocationAbbr(locations, limit); + } + } + /* * (non-Javadoc) *