diff --git a/megameklab/src/megameklab/ui/mek/BMCriticalTransferHandler.java b/megameklab/src/megameklab/ui/mek/BMCriticalTransferHandler.java index 926899ce0..89a7df838 100644 --- a/megameklab/src/megameklab/ui/mek/BMCriticalTransferHandler.java +++ b/megameklab/src/megameklab/ui/mek/BMCriticalTransferHandler.java @@ -22,11 +22,7 @@ import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.Vector; +import java.util.*; import javax.swing.JComboBox; import javax.swing.JComponent; @@ -131,7 +127,7 @@ private boolean addSplitLocationEquipment(Mek mek, Mounted eq, int slotNumber // It's obvious that the equipment can't be placed on an occupied slot, so in // that case // a good free slot can be chosen in the location - if (freePrimarySlots == 0) { + if (freePrimarySlots < neededTotalSlots) { int maxSpace = MekUtil.getMaxContiguousNumOfCrits(mek, location, true); slotNumber = MekUtil.findSlotWithContiguousNumOfCrits(mek, location, maxSpace); freePrimarySlots = MekUtil.availableContiguousCrits(mek, location, slotNumber, true); @@ -221,16 +217,33 @@ public boolean importData(TransferSupport info) { } try { - Mounted eq = getUnit().getEquipment(Integer.parseInt( - (String) t.getTransferData(DataFlavor.stringFlavor))); + var data = (String) t.getTransferData(DataFlavor.stringFlavor); + boolean fixedEquipment = false; + int fixedLocation = Entity.LOC_NONE; + Mounted eq; + if (!data.contains(":")) { + eq = getUnit().getEquipment(Integer.parseInt(data)); + } else { + fixedEquipment = true; + var parts = Arrays.stream(data.split(":")).mapToInt(Integer::parseInt).toArray(); + eq = getUnit().getEquipment(parts[0]); + fixedLocation = parts[1]; + if (fixedLocation != location) { + PopupMessages.showInvalidLocationInfo(null, eq.getName(), getUnit().getLocationName(location)); + return false; + } + } // If this equipment is already mounted, clear the criticals it's mounted in - if (eq.getLocation() != Entity.LOC_NONE - || eq.getSecondLocation() != Entity.LOC_NONE) { - UnitUtil.removeCriticals(getUnit(), eq); - UnitUtil.changeMountStatus(getUnit(), eq, Entity.LOC_NONE, -1, false); + if (!fixedEquipment) { + if (eq.getLocation() != Entity.LOC_NONE || eq.getSecondLocation() != Entity.LOC_NONE) { + UnitUtil.removeCriticals(getUnit(), eq); + UnitUtil.changeMountStatus(getUnit(), eq, Entity.LOC_NONE, -1, false); + } else { + eq.setOmniPodMounted(UnitUtil.canPodMount(getUnit(), eq)); + } } else { - eq.setOmniPodMounted(UnitUtil.canPodMount(getUnit(), eq)); + UnitUtil.removeCriticals(getUnit(), eq, fixedLocation); } StringBuffer errors = new StringBuffer(); @@ -286,7 +299,7 @@ public boolean canImport(TransferSupport info) { // check if the dragged mounted should be transferrable Mounted mounted = null; try { - int index = Integer.parseInt((String) info.getTransferable().getTransferData(DataFlavor.stringFlavor)); + int index = Integer.parseInt(((String) info.getTransferable().getTransferData(DataFlavor.stringFlavor)).split(":")[0]); mounted = getUnit().getEquipment(index); } catch (Exception e) { logger.error("", e); @@ -295,23 +308,30 @@ public boolean canImport(TransferSupport info) { if (mounted == null) { return false; } - // stuff that has a fixed location is also not transferable - return !UnitUtil.isFixedLocationSpreadEquipment(mounted.getType()); + + return true; } @Override protected Transferable createTransferable(JComponent c) { Mounted mount = null; + int location = Entity.LOC_NONE; if (c instanceof JTable) { JTable table = (JTable) c; mount = (Mounted) table.getModel().getValueAt(table.getSelectedRow(), CriticalTableModel.EQUIPMENT); } else if (c instanceof BAASBMDropTargetCriticalList) { BAASBMDropTargetCriticalList list = (BAASBMDropTargetCriticalList) c; mount = list.getMounted(); + location = list.getCritLocation(); } if (mount != null) { - parentView.markUnavailableLocations(mount); - return new StringSelection(Integer.toString(getUnit().getEquipmentNum(mount))); + if (UnitUtil.isFixedLocationSpreadEquipment(mount.getType())) { + parentView.markUnavailableLocations(location); + return new StringSelection("%d:%d".formatted(getUnit().getEquipmentNum(mount), location)); + } else { + parentView.markUnavailableLocations(mount); + return new StringSelection(Integer.toString(getUnit().getEquipmentNum(mount))); + } } else { return null; } diff --git a/megameklab/src/megameklab/ui/mek/BMCriticalView.java b/megameklab/src/megameklab/ui/mek/BMCriticalView.java index 357761414..67c73911c 100644 --- a/megameklab/src/megameklab/ui/mek/BMCriticalView.java +++ b/megameklab/src/megameklab/ui/mek/BMCriticalView.java @@ -206,6 +206,15 @@ private String caseSuffix(int location) { } } + /** + * Darkens all crit blocks other than the one for the given location + */ + public void markUnavailableLocations(int location) { + currentCritBlocks.stream() + .filter(b -> b.getCritLocation() != location) + .forEach(b -> b.setDarkened(true)); + } + /** * Darkens all crit blocks that are unavailable to the given equipment, e.g. all but Torsos for CASE. */ diff --git a/megameklab/src/megameklab/ui/mek/BMStructureTab.java b/megameklab/src/megameklab/ui/mek/BMStructureTab.java index da286c386..d506a55d8 100644 --- a/megameklab/src/megameklab/ui/mek/BMStructureTab.java +++ b/megameklab/src/megameklab/ui/mek/BMStructureTab.java @@ -930,6 +930,7 @@ public void enhancementChanged(EquipmentType enhancement) { refresh.refreshPreview(); refresh.refreshStatus(); refresh.refreshSummary(); + refresh.refreshEquipment(); } @Override diff --git a/megameklab/src/megameklab/util/MekUtil.java b/megameklab/src/megameklab/util/MekUtil.java index f25d046a2..bc6edb7ba 100644 --- a/megameklab/src/megameklab/util/MekUtil.java +++ b/megameklab/src/megameklab/util/MekUtil.java @@ -1150,16 +1150,18 @@ public static int getCoarseOrdering(Mek mek, Mounted mounted) { return 4; } else if (mounted.getType() instanceof AmmoType) { return 5; - } else if (mounted.getType().isHittable()) { + } else if (mounted.getType().isHittable() && !mounted.getType().hasFlag(MiscType.F_SCM)) { return 6; - } else if (isCASE(mounted)) { + } else if(mounted.getType().hasFlag(MiscType.F_SCM)) { return 7; - } else if (EquipmentType.isStructureType(mounted.getType())) { + } else if (isCASE(mounted)) { return 8; - } else if (EquipmentType.isArmorType(mounted.getType())) { + } else if (EquipmentType.isStructureType(mounted.getType())) { return 9; - } else { + } else if (EquipmentType.isArmorType(mounted.getType())) { return 10; + } else { + return 11; } } diff --git a/megameklab/src/megameklab/util/UnitUtil.java b/megameklab/src/megameklab/util/UnitUtil.java index c6f170075..61e2502d7 100644 --- a/megameklab/src/megameklab/util/UnitUtil.java +++ b/megameklab/src/megameklab/util/UnitUtil.java @@ -390,6 +390,39 @@ public static void removeCriticals(Entity unit, Mounted eq) { } } + /** + * Sets the corresponding critical slots to null for the Mounted object in the given location. + * + * @param unit The entity + * @param eq The equipment to test + * @param loc The location to remove crits from. + */ + public static void removeCriticals(Entity unit, Mounted eq, int loc) { + if (eq.getLocation() == Entity.LOC_NONE) { + return; + } + for (int slot = 0; slot < unit.getNumberOfCriticals(loc); slot++) { + CriticalSlot cs = unit.getCritical(loc, slot); + if ((cs != null) + && (cs.getType() == CriticalSlot.TYPE_EQUIPMENT)) { + if (cs.getMount().equals(eq)) { + // If there are two pieces of equipment in this slot, + // remove first one, and replace it with the second + if (cs.getMount2() != null) { + cs.setMount(cs.getMount2()); + cs.setMount2(null); + } else { // If it's the only Mounted, clear the slot + cs = null; + unit.setCritical(loc, slot, cs); + } + } else if ((cs.getMount2() != null) + && cs.getMount2().equals(eq)) { + cs.setMount2(null); + } + } + } + } + public static void addMounted(Entity unit, Mounted mounted, int loc, boolean rearMounted) throws LocationFullException { unit.addEquipment(mounted, loc, rearMounted);