/* * MegaMekLab - Copyright (C) 2008 * * Original author - jtighe (torren@users.sourceforge.net) * * This program 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 2 of the License, or (at your option) * any later version. * * This program 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. */ package megameklab.com.util.Mech; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Vector; import javax.swing.JList; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import megamek.common.AmmoType; import megamek.common.BattleArmor; import megamek.common.BipedMech; import megamek.common.CriticalSlot; import megamek.common.Entity; import megamek.common.Mech; import megamek.common.MechFileParser; import megamek.common.MiscType; import megamek.common.Mounted; import megamek.common.TripodMech; import megamek.common.WeaponType; import megamek.common.loaders.EntityLoadingException; import megamek.common.verifier.TestBattleArmor; import megamek.common.weapons.ACWeapon; import megamek.common.weapons.GaussWeapon; import megamek.common.weapons.LBXACWeapon; import megamek.common.weapons.PPCWeapon; import megamek.common.weapons.UACWeapon; import megameklab.com.ui.EntitySource; import megameklab.com.util.CritListCellRenderer; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; public class DropTargetCriticalList<E> extends JList<E> implements MouseListener { /** * */ private static final long serialVersionUID = 6847511182922982125L; private EntitySource eSource; private RefreshListener refresh; private boolean buildView = false; public DropTargetCriticalList(Vector<E> vector, EntitySource eSource, RefreshListener refresh, boolean buildView) { super(vector); setDragEnabled(true); this.eSource = eSource; this.refresh = refresh; this.buildView = buildView; setCellRenderer(new CritListCellRenderer(eSource.getEntity(), buildView)); addMouseListener(this); setTransferHandler(new CriticalTransferHandler(eSource, refresh)); } private void changeMountStatus(Mounted eq, int location, boolean rear) { changeMountStatus(eq, location, -1, rear); } private void changeMountStatus(Mounted eq, int location, int secondaryLocation, boolean rear) { if (getUnit() instanceof BattleArmor){ eq.setBaMountLoc(location); } else { UnitUtil.changeMountStatus(getUnit(), eq, location, secondaryLocation, rear); } if (refresh != null) { refresh.refreshAll(); } } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { if (buildView) { if (e.getButton() == MouseEvent.BUTTON2) { setSelectedIndex(locationToIndex(e.getPoint())); removeCrit(); } else if (e.getButton() == MouseEvent.BUTTON3) { setSelectedIndex(locationToIndex(e.getPoint())); if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) { removeCrit(); return; } int location = getCritLocation(); JPopupMenu popup = new JPopupMenu(); CriticalSlot cs = getCrit(); final Mounted mount = getMounted(); if ((e.getModifiersEx() & InputEvent.ALT_DOWN_MASK) != 0) { changeWeaponFacing(!mount.isRearMounted()); return; } if (mount != null && (e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0) { changeOmniMounting(!mount.isOmniPodMounted()); return; } if (mount != null) { JMenuItem info; if (!UnitUtil.isFixedLocationSpreadEquipment(mount .getType())) { popup.setAutoscrolls(true); info = new JMenuItem("Remove " + mount.getName()); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { removeCrit(); } }); popup.add(info); } info = new JMenuItem("Delete " + mount.getName()); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { removeMount(); } }); if (!((getUnit() instanceof BattleArmor) && UnitUtil.isFixedLocationSpreadEquipment(mount .getType()))){ popup.add(info); } // Allow making this a sort weapon if ((mount.getType() instanceof WeaponType) && !mount.isSquadSupportWeapon() && mount.getLocation() == BattleArmor.LOC_SQUAD && (getUnit() instanceof BattleArmor) && ((BattleArmor)getUnit()).getChassisType() != BattleArmor.CHASSIS_TYPE_QUAD){ info = new JMenuItem("Mount as squad support weapon"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { mount.setSquadSupportWeapon(true); if (refresh != null) { refresh.refreshAll(); } } }); popup.add(info); } // Adding ammo as a squad support mount is slightly different if ((mount.getType() instanceof AmmoType) && !mount.getType().hasFlag(WeaponType.F_MISSILE) && !mount.isSquadSupportWeapon() && mount.getLocation() == BattleArmor.LOC_SQUAD && (getUnit() instanceof BattleArmor) && ((BattleArmor)getUnit()).getChassisType() != BattleArmor.CHASSIS_TYPE_QUAD){ boolean enabled = false; for (Mounted weapon : getUnit().getWeaponList()){ WeaponType wtype = (WeaponType)weapon.getType(); if (weapon.isSquadSupportWeapon() && AmmoType.isAmmoValid(mount, wtype)){ enabled = true; } } info = new JMenuItem("Mount as squad support weapon"); info.setEnabled(enabled); info.setToolTipText("Ammo can only be squad mounted along " + "with a weapon that uses it"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { mount.setSquadSupportWeapon(true); if (refresh != null) { refresh.refreshAll(); } } }); popup.add(info); } // Allow removing squad support weapon if (mount.isSquadSupportWeapon()){ info = new JMenuItem("Remove squad support weapon mount"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { mount.setSquadSupportWeapon(false); // Can't have squad support weapon ammo with no // squad support weapon for (Mounted ammo : getUnit().getAmmo()){ ammo.setSquadSupportWeapon(false); } if (refresh != null) { refresh.refreshAll(); } } }); popup.add(info); } // Right-clicked on a DWP that has an attached weapon if (mount.getType().hasFlag(MiscType.F_DETACHABLE_WEAPON_PACK) && mount.getLinked() != null){ info = new JMenuItem("Remove attached weapon"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Mounted attached = mount.getLinked(); attached.setDWPMounted(false); mount.setLinked(null); mount.setLinkedBy(null); attached.setLinked(null); attached.setLinkedBy(null); if (refresh != null) { refresh.refreshAll(); } } }); popup.add(info); } // Right-clicked on a AP Mount that has an attached weapon if (mount.getType().hasFlag(MiscType.F_AP_MOUNT) && mount.getLinked() != null){ info = new JMenuItem("Remove attached weapon"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Mounted attached = mount.getLinked(); attached.setAPMMounted(false); mount.setLinked(null); mount.setLinkedBy(null); attached.setLinked(null); attached.setLinkedBy(null); if (refresh != null) { refresh.refreshAll(); } } }); popup.add(info); } if ((mount.getLocation() != Mech.LOC_LARM) && (mount.getLocation() != Mech.LOC_RARM)) { if (mount.getType() instanceof WeaponType) { if (getUnit().hasWorkingMisc(MiscType.F_QUAD_TURRET, -1, mount.getLocation()) || getUnit().hasWorkingMisc( MiscType.F_SHOULDER_TURRET, -1, mount.getLocation()) || (getUnit().hasWorkingMisc( MiscType.F_HEAD_TURRET, -1, Mech.LOC_CT) && (mount .getLocation() == Mech.LOC_HEAD))) { if (!mount.isMechTurretMounted()) { info = new JMenuItem("Mount " + mount.getName() + " in Turret"); info.addActionListener(new ActionListener() { public void actionPerformed( ActionEvent e) { changeTurretMount(true); } }); popup.add(info); } else { info = new JMenuItem("Remove " + mount.getName() + " from Turret"); info.addActionListener(new ActionListener() { public void actionPerformed( ActionEvent e) { changeTurretMount(false); } }); popup.add(info); } } } if (!(getUnit() instanceof BattleArmor) && ((mount.getType() instanceof WeaponType) || ((mount .getType() instanceof MiscType) && mount .getType() .hasFlag(MiscType.F_LIFTHOIST)))) { if (!mount.isRearMounted()) { info = new JMenuItem("Make " + mount.getName() + " Rear Facing"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changeWeaponFacing(true); } }); popup.add(info); } else { info = new JMenuItem("Make " + mount.getName() + " Forward Facing"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changeWeaponFacing(false); } }); popup.add(info); } } } // Allow number of shots selection if ((getUnit() instanceof BattleArmor) && mount.getType() instanceof AmmoType){ AmmoType at = (AmmoType) mount.getType(); int maxNumShots = TestBattleArmor.NUM_SHOTS_PER_CRIT; int stepSize = 1; if (at.getAmmoType() == AmmoType.T_BA_TUBE) { maxNumShots = TestBattleArmor.NUM_SHOTS_PER_CRIT_TA; stepSize = 2; } for (int i = at.getShots(); i <= maxNumShots; i += stepSize){ if (i == mount.getBaseShotsLeft()){ continue; } info = new JMenuItem("Set Shots: " + i); final int shots = i; info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { mount.setShotsLeft(shots); if (refresh != null) { refresh.refreshAll(); } } }); popup.add(info); } } if (getUnit().isOmni() && !mount.getType().isOmniFixedOnly()) { if (mount.isOmniPodMounted()) { info = new JMenuItem("Change to fixed mount"); info.addActionListener(ev -> changeOmniMounting(false)); popup.add(info); } else if (UnitUtil.canPodMount(getUnit(), mount)) { info = new JMenuItem("Change to pod mount"); info.addActionListener(ev -> changeOmniMounting(true)); popup.add(info); } } } if ((getUnit() instanceof BipedMech || getUnit() instanceof TripodMech) && ((location == Mech.LOC_LARM) || (location == Mech.LOC_RARM))) { boolean canHaveLowerArm = true; if (getUnit().isOmni()) { int numCrits = getUnit().getNumberOfCriticals(location); for (int slot = 0; slot < numCrits; slot++) { CriticalSlot crit = getUnit().getCritical(location, slot); if (crit == null) { continue; } if (crit.getType() == CriticalSlot.TYPE_SYSTEM) { continue; } Mounted m = crit.getMount(); if ((m.getType() instanceof GaussWeapon) || (m.getType() instanceof ACWeapon) || (m.getType() instanceof UACWeapon) || (m.getType() instanceof LBXACWeapon) || (m.getType() instanceof PPCWeapon)) { canHaveLowerArm = false; } } } popup.addSeparator(); popup.setAutoscrolls(true); if (canHaveLowerArm && ((getUnit().getCritical(location, 3) == null) || (getUnit() .getCritical(location, 3).getType() != CriticalSlot.TYPE_SYSTEM))) { JMenuItem info = new JMenuItem("Add Hand"); info.setActionCommand(Integer.toString(location)); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { addHand(Integer.parseInt(e.getActionCommand())); } }); popup.add(info); } else if ((getUnit().getCritical(location, 3) != null) && (getUnit().getCritical(location, 3).getType() == CriticalSlot.TYPE_SYSTEM)) { JMenuItem info = new JMenuItem("Remove Hand"); info.setActionCommand(Integer.toString(location)); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { removeHand(Integer.parseInt(e .getActionCommand())); } }); popup.add(info); } if (canHaveLowerArm && ((getUnit().getCritical(location, 2) == null) || (getUnit() .getCritical(location, 2).getType() != CriticalSlot.TYPE_SYSTEM))) { JMenuItem info = new JMenuItem("Add Lower Arm"); info.setActionCommand(Integer.toString(location)); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { addArm(Integer.parseInt(e.getActionCommand())); } }); popup.add(info); } else if ((getUnit().getCritical(location, 2) != null) && (getUnit().getCritical(location, 2).getType() == CriticalSlot.TYPE_SYSTEM)) { JMenuItem info = new JMenuItem("Remove Lower Arm"); info.setActionCommand(Integer.toString(location)); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { removeArm(Integer.parseInt(e.getActionCommand())); } }); popup.add(info); } } if (UnitUtil.isArmorable(cs) && !(getUnit() instanceof BattleArmor) && ((UnitUtil.getUnitTechType(getUnit()) == UnitUtil.TECH_EXPERIMENTAL) || (UnitUtil.getUnitTechType(getUnit()) == UnitUtil.TECH_UNOFFICAL))) { popup.addSeparator(); if (cs.isArmored()) { JMenuItem info = new JMenuItem("Remove Armoring"); info.setActionCommand(Integer.toString(location)); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changeArmoring(); } }); popup.add(info); } else if (!(getUnit() instanceof Mech && ((Mech)getUnit()).isSuperHeavy())) { JMenuItem info = new JMenuItem("Add Armoring"); info.setActionCommand(Integer.toString(location)); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changeArmoring(); } }); popup.add(info); } } if (popup.getComponentCount() > 0) { popup.show(this, e.getX(), e.getY()); } } } } public void mouseReleased(MouseEvent e) { } public Mounted getMounted() { // BattleArmor doesn't have a proper critical system like other units // so they are handled specially if (getUnit() instanceof BattleArmor){ // The names for this list should be of the form <eq>:<slot>:<eqId> String[] split = ((String)this.getSelectedValue()).split(":"); if (split.length > 2){ int eqId = Integer.parseInt(split[2]); return getUnit().getEquipment(eqId); } return null; } CriticalSlot crit = getCrit(); Mounted mount = null; try { if ((crit != null) && (crit.getType() == CriticalSlot.TYPE_EQUIPMENT)) { return crit.getMount(); } } catch (Exception ex) { ex.printStackTrace(); } return mount; } public CriticalSlot getCrit() { int slot = getSelectedIndex(); int location = getCritLocation(); CriticalSlot crit = null; if ((slot >= 0) && (slot < getUnit().getNumberOfCriticals(location))) { crit = getUnit().getCritical(location, slot); } return crit; } public void removeMount() { Mounted mounted = getMounted(); if (mounted == null) { return; } if (UnitUtil.isStructure(mounted.getType())) { UnitUtil.removeISorArmorMounts(getUnit(), true); } if (UnitUtil.isArmor(mounted.getType())) { UnitUtil.removeISorArmorMounts(getUnit(), false); } else if (mounted.getType().isSpreadable()) { UnitUtil.removeAllMounteds(getUnit(), mounted.getType()); } else { UnitUtil.removeCriticals(getUnit(), mounted); UnitUtil.removeMounted(getUnit(), mounted); } // Check linkings after you remove everything. try { MechFileParser.postLoadInit(getUnit()); } catch (EntityLoadingException ele) { // do nothing. } catch (Exception ex) { ex.printStackTrace(); } if (refresh != null) { refresh.refreshAll(); } } public void removeCrit() { CriticalSlot crit = getCrit(); Mounted mounted = getMounted(); if (mounted == null) { return; } // BattleArmor doens't use the crit system, we we can just remove the // mounted and be done if (getUnit() instanceof BattleArmor){ changeMountStatus(mounted, BattleArmor.MOUNT_LOC_NONE, false); return; } UnitUtil.removeCriticals(getUnit(), mounted); // Check linkings after you remove everything. try { MechFileParser.postLoadInit(getUnit()); } catch (EntityLoadingException ele) { // do nothing. } catch (Exception ex) { ex.printStackTrace(); } if ((crit != null) && (crit.getType() == CriticalSlot.TYPE_EQUIPMENT)) { changeMountStatus(mounted, Entity.LOC_NONE, false); } } private void changeWeaponFacing(boolean rear) { Mounted mount = getMounted(); int location = getCritLocation(); changeMountStatus(mount, location, rear); } private void changeOmniMounting(boolean pod) { Mounted mount = getMounted(); if (!pod || UnitUtil.canPodMount(getUnit(), mount)) { mount.setOmniPodMounted(pod); if (getCrit().getMount2() != null) { getCrit().getMount2().setOmniPodMounted(pod); } } if (refresh != null) { refresh.refreshAll(); } } private void changeTurretMount(boolean turret) { getMounted().setMechTurretMounted(turret); if (getMounted().getLinkedBy() != null) { getMounted().getLinkedBy().setMechTurretMounted(turret); } if (refresh != null) { refresh.refreshAll(); } } private int getCritLocation() { if (getUnit() instanceof BattleArmor){ String[] split = getName().split(":"); return Integer.parseInt(split[0]); } else { return Integer.parseInt(getName()); } } private void addHand(int location) { CriticalSlot cs = getUnit().getCritical(location, 3); if (cs != null) { Mounted mount = cs.getMount(); UnitUtil.removeCriticals(getUnit(), mount); changeMountStatus(mount, Entity.LOC_NONE, false); } getUnit().setCritical(location, 3, new CriticalSlot( CriticalSlot.TYPE_SYSTEM, Mech.ACTUATOR_HAND)); addArm(location); } private void removeHand(int location) { if (getUnit() instanceof BipedMech || getUnit() instanceof TripodMech) { UnitUtil.removeHand((Mech) getUnit(), location); if (refresh != null) { refresh.refreshAll(); } } } private void removeArm(int location) { if (getUnit() instanceof BipedMech || getUnit() instanceof TripodMech) { UnitUtil.removeArm((Mech)getUnit(),location); if (refresh != null) { refresh.refreshAll(); } } } private void addArm(int location) { CriticalSlot cs = getUnit().getCritical(location, 2); if ((cs != null) && (cs.getType() == CriticalSlot.TYPE_EQUIPMENT)) { Mounted mount = cs.getMount(); UnitUtil.removeCriticals(getUnit(), mount); changeMountStatus(mount, Entity.LOC_NONE, false); } getUnit().setCritical(location, 2, new CriticalSlot( CriticalSlot.TYPE_SYSTEM, Mech.ACTUATOR_LOWER_ARM)); if (refresh != null) { refresh.refreshAll(); } } private void changeArmoring() { CriticalSlot cs = getCrit(); if (cs != null) { if (cs.getType() == CriticalSlot.TYPE_EQUIPMENT) { Mounted mount = getMounted(); mount.setArmored(!cs.isArmored()); UnitUtil.updateCritsArmoredStatus(getUnit(), mount); } else { cs.setArmored(!cs.isArmored()); UnitUtil.updateCritsArmoredStatus(getUnit(), cs, getCritLocation()); } } // Check linkings after you remove everything. try { MechFileParser.postLoadInit(getUnit()); } catch (EntityLoadingException ele) { // do nothing. } catch (Exception ex) { ex.printStackTrace(); } if (refresh != null) { refresh.refreshAll(); } } public Entity getUnit() { return eSource.getEntity(); } }