From 9685a227ae44cacc8f5e608059c58f75490ae831 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Wed, 5 Jun 2024 20:42:50 -0500 Subject: [PATCH 1/3] feat: added random unit quality generator - Implemented getRandomUnitQuality method to generate quality of unit based on 2d6 roll and a modifier --- MekHQ/src/mekhq/campaign/unit/Unit.java | 46 +++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/unit/Unit.java b/MekHQ/src/mekhq/campaign/unit/Unit.java index bc74e5e4e2..d5ed0207bc 100644 --- a/MekHQ/src/mekhq/campaign/unit/Unit.java +++ b/MekHQ/src/mekhq/campaign/unit/Unit.java @@ -23,6 +23,7 @@ import megamek.Version; import megamek.client.ui.swing.tileset.EntityImage; +import megamek.codeUtilities.MathUtility; import megamek.common.*; import megamek.common.InfantryBay.PlatoonType; import megamek.common.annotations.Nullable; @@ -5316,7 +5317,7 @@ public Money getFuelCost() { fuelCost = fuelCost.plus(getTonsBurnDay(entity));// * 3 * 15000; } else if (entity instanceof ConvFighter) { fuelCost = fuelCost.plus(getFighterFuelCost(entity)); - } else if (entity instanceof megamek.common.Aero) { + } else if (entity instanceof Aero) { fuelCost = fuelCost.plus(((Aero) entity).getFuelTonnage() * 4.0 * 15000.0); } else if ((entity instanceof Tank) || (entity instanceof Mech)) { fuelCost = fuelCost.plus(getVehicleFuelCost(entity)); @@ -5356,7 +5357,7 @@ public double getTonsBurnDay(Entity e) { return (tonsburnday * 15 * 15000); } else if ((e instanceof SmallCraft)) { return (1.84 * 15 * 15000); - } else if (e instanceof megamek.common.Jumpship) { + } else if (e instanceof Jumpship) { if (e.getWeight() < 50000) { tonsburnday = 2.82; } else if (e.getWeight() < 100000) { @@ -5366,7 +5367,7 @@ public double getTonsBurnDay(Entity e) { } else { tonsburnday = 39.52; } - if (e instanceof megamek.common.Warship) { + if (e instanceof Warship) { return (tonsburnday * 15 * 15000); } return (tonsburnday * 3 * 15000); @@ -5689,4 +5690,43 @@ public void fixReferences(Campaign campaign) { transportedUnits = newTransportedUnits; } } + + /** + * Generates a random unit quality based on a 2d6 roll and a modifier. + * This table is based on the AtB Mek Quality table, but is still useful outside of that ruleset + * + * @param modifier the modifier to be applied to the 2d6 roll + * @return an integer representing the generated unit quality + * @throws IllegalStateException if an unexpected value is encountered during the switch statement + */ + public static int getRandomUnitQuality(int modifier) { + int roll = MathUtility.clamp( + (Compute.d6(2) + modifier), + 2, + 12 + ); + + switch (roll) { + case 2: + case 3: + case 4: + case 5: + return Part.QUALITY_A; + case 6: + case 7: + case 8: + return Part.QUALITY_B; + case 9: + case 10: + return Part.QUALITY_C; + case 11: + return Part.QUALITY_D; + case 12: + return Part.QUALITY_F; + default: + throw new IllegalStateException("Unexpected value in mekhq/campaign/unit/Unit.java/getRandomUnitQuality: " + roll); + } + + + } } From 0061dede5a68a37818a83d76c4d092eb902718db Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Wed, 5 Jun 2024 20:53:56 -0500 Subject: [PATCH 2/3] feat: added option for random new unit quality - Added checkbox for enabling/disabling random new unit quality - Updated related settings and tooltips in CampaignOptionsDialog.properties - Updated set and get methods in CampaignOptions.java - Adjusted the UI to accommodate the new option in CampaignOptionsPane.java --- .../CampaignOptionsDialog.properties | 2 ++ MekHQ/src/mekhq/campaign/CampaignOptions.java | 13 ++++++++++ MekHQ/src/mekhq/campaign/unit/Unit.java | 2 -- .../mekhq/gui/panes/CampaignOptionsPane.java | 26 ++++++++++++++----- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 050cd54ab7..17887905ee 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -36,6 +36,8 @@ useQualityMaintenance.text=Use quality modifiers in maintenance checks useQualityMaintenance.toolTipText=If checked, quality modifiers will be added to maintenance checks (WARNING: this will lead to unstable quality ratings over time) reverseQualityNames.text=Reverse quality names reverseQualityNames.toolTipText=If checked, quality name reporting will be reversed so that A is the best and F is the worst +chkUseRandomUnitQualities.text=Random New Unit Quality +chkUseRandomUnitQualities.toolTipText=If checked, the quality of new units is randomized when they are added to the campaign. Otherwise, quality will always default to D. useUnofficialMaintenance.text=Only damage parts that are already at worst quality (Unofficial) useUnofficialMaintenance.toolTipText=When this option is checked and you are using quality maintenance,
the margin of failure rolls for damaging parts only happen for parts that are already rated at the lowest level. logMaintenance.text=Log maintenance rolls in log file diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index ebdbef99d2..fafa495800 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -128,6 +128,7 @@ public static String getTransitUnitName(final int unit) { private int maintenanceBonus; private boolean useQualityMaintenance; private boolean reverseQualityNames; + private boolean useRandomUnitQualities; private boolean useUnofficialMaintenance; private boolean logMaintenance; @@ -563,6 +564,7 @@ public CampaignOptions() { maintenanceBonus = -1; useQualityMaintenance = true; reverseQualityNames = false; + setUseRandomUnitQualities(true); useUnofficialMaintenance = false; logMaintenance = false; @@ -1167,6 +1169,14 @@ public void setReverseQualityNames(final boolean reverseQualityNames) { this.reverseQualityNames = reverseQualityNames; } + public boolean isUseRandomUnitQualities() { + return useRandomUnitQualities; + } + + public void setUseRandomUnitQualities(final boolean useRandomUnitQualities) { + this.useRandomUnitQualities = useRandomUnitQualities; + } + public boolean isUseUnofficialMaintenance() { return useUnofficialMaintenance; } @@ -4102,6 +4112,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "maintenanceBonus", maintenanceBonus); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useQualityMaintenance", useQualityMaintenance); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "reverseQualityNames", reverseQualityNames); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomUnitQualities", isUseRandomUnitQualities()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useUnofficialMaintenance", isUseUnofficialMaintenance()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "checkMaintenance", checkMaintenance); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "maxAcquisitions", maxAcquisitions); @@ -4490,6 +4501,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.useQualityMaintenance = Boolean.parseBoolean(wn2.getTextContent()); } else if (wn2.getNodeName().equalsIgnoreCase("reverseQualityNames")) { retVal.reverseQualityNames = Boolean.parseBoolean(wn2.getTextContent()); + } else if (wn2.getNodeName().equalsIgnoreCase("useRandomUnitQualities")) { + retVal.setUseRandomUnitQualities(Boolean.parseBoolean(wn2.getTextContent())); } else if (wn2.getNodeName().equalsIgnoreCase("useUnofficialMaintenance") || wn2.getNodeName().equalsIgnoreCase("useUnofficalMaintenance")) { // Legacy, 0.49.12 Removal retVal.setUseUnofficialMaintenance(Boolean.parseBoolean(wn2.getTextContent())); diff --git a/MekHQ/src/mekhq/campaign/unit/Unit.java b/MekHQ/src/mekhq/campaign/unit/Unit.java index d5ed0207bc..f1b9120114 100644 --- a/MekHQ/src/mekhq/campaign/unit/Unit.java +++ b/MekHQ/src/mekhq/campaign/unit/Unit.java @@ -5726,7 +5726,5 @@ public static int getRandomUnitQuality(int modifier) { default: throw new IllegalStateException("Unexpected value in mekhq/campaign/unit/Unit.java/getRandomUnitQuality: " + roll); } - - } } diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index b741d7bd38..0c57214380 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -143,6 +143,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JSpinner spnMaintenanceBonus; private JCheckBox useQualityMaintenance; private JCheckBox reverseQualityNames; + private JCheckBox chkUseRandomUnitQualities; private JCheckBox useUnofficialMaintenance; private JCheckBox logMaintenance; //endregion Repair and Maintenance Tab @@ -919,6 +920,7 @@ private JScrollPane createRepairAndMaintenanceTab() { useQualityMaintenance.setEnabled(true); useUnofficialMaintenance.setEnabled(true); reverseQualityNames.setEnabled(true); + chkUseRandomUnitQualities.setEnabled(true); spnMaintenanceBonus.setEnabled(true); logMaintenance.setEnabled(true); } else { @@ -926,6 +928,7 @@ private JScrollPane createRepairAndMaintenanceTab() { useQualityMaintenance.setEnabled(false); useUnofficialMaintenance.setEnabled(false); reverseQualityNames.setEnabled(false); + chkUseRandomUnitQualities.setEnabled(false); spnMaintenanceBonus.setEnabled(false); logMaintenance.setEnabled(false); } @@ -984,19 +987,26 @@ private JScrollPane createRepairAndMaintenanceTab() { gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; panSubMaintenance.add(reverseQualityNames, gridBagConstraints); + chkUseRandomUnitQualities = new JCheckBox(resources.getString("chkUseRandomUnitQualities.text")); + chkUseRandomUnitQualities.setToolTipText(resources.getString("chkUseRandomUnitQualities.toolTipText")); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.fill = GridBagConstraints.NONE; + gridBagConstraints.weightx = 0.0; + gridBagConstraints.weighty = 0.0; + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + panSubMaintenance.add(chkUseRandomUnitQualities, gridBagConstraints); + reverseQualityNames.addActionListener(evt -> { - if (reverseQualityNames.isSelected()) { - recreateFinancesPanel(true); - } else { - recreateFinancesPanel(false); - } + recreateFinancesPanel(reverseQualityNames.isSelected()); }); useUnofficialMaintenance = new JCheckBox(resources.getString("useUnofficialMaintenance.text")); useUnofficialMaintenance.setToolTipText(resources.getString("useUnofficialMaintenance.toolTipText")); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 5; + gridBagConstraints.gridy = 6; gridBagConstraints.fill = GridBagConstraints.NONE; gridBagConstraints.weightx = 0.0; gridBagConstraints.weighty = 0.0; @@ -1006,7 +1016,7 @@ private JScrollPane createRepairAndMaintenanceTab() { logMaintenance = new JCheckBox(resources.getString("logMaintenance.text")); logMaintenance.setToolTipText(resources.getString("logMaintenance.toolTipText")); logMaintenance.setName("logMaintenance"); - gridBagConstraints.gridy = 6; + gridBagConstraints.gridy = 7; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; panSubMaintenance.add(logMaintenance, gridBagConstraints); @@ -6950,6 +6960,7 @@ public void setOptions(@Nullable CampaignOptions options, spnMaintenanceBonus.setValue(options.getMaintenanceBonus()); useQualityMaintenance.setSelected(options.isUseQualityMaintenance()); reverseQualityNames.setSelected(options.isReverseQualityNames()); + chkUseRandomUnitQualities.setSelected(options.isUseRandomUnitQualities()); useUnofficialMaintenance.setSelected(options.isUseUnofficialMaintenance()); logMaintenance.setSelected(options.isLogMaintenance()); //endregion Repair and Maintenance Tab @@ -7505,6 +7516,7 @@ public void updateOptions() { options.setCheckMaintenance(checkMaintenance.isSelected()); options.setUseQualityMaintenance(useQualityMaintenance.isSelected()); options.setReverseQualityNames(reverseQualityNames.isSelected()); + options.setUseRandomUnitQualities(chkUseRandomUnitQualities.isSelected()); options.setUseUnofficialMaintenance(useUnofficialMaintenance.isSelected()); options.setLogMaintenance(logMaintenance.isSelected()); options.setMaintenanceBonus((Integer) spnMaintenanceBonus.getValue()); From 606a8ed0b5b729e89ea35b64bff95376cf14438d Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Wed, 5 Jun 2024 21:37:17 -0500 Subject: [PATCH 3/3] feat: Added support for random unit qualities across multiple classes --- MekHQ/src/mekhq/campaign/Campaign.java | 12 ++++++-- MekHQ/src/mekhq/campaign/Quartermaster.java | 13 ++++++-- .../mekhq/campaign/mission/AtBContract.java | 18 +++++++++-- .../storytrigger/AddUnitStoryTrigger.java | 15 ++++++++-- .../AbstractCompanyGenerator.java | 30 +++++++++++++++++-- MekHQ/src/mekhq/gui/CampaignGUI.java | 9 +++++- .../adapter/ProcurementTableMouseAdapter.java | 13 ++++++-- MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java | 12 +++++++- .../gui/dialog/MekHQUnitSelectorDialog.java | 8 ++++- .../gui/dialog/PersonnelMarketDialog.java | 11 ++++++- .../mekhq/campaign/QuartermasterTest.java | 10 +++---- 11 files changed, 128 insertions(+), 23 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 2937768e67..6eaa9f90d8 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -663,7 +663,7 @@ public void purchaseShipSearchResult() { try { mechFileParser = new MechFileParser(ms.getSourceFile(), ms.getEntryName()); } catch (Exception ex) { - LogManager.getLogger().error("Unable to load unit: " + ms.getEntryName(), ex); + LogManager.getLogger().error("Unable to load unit: {}", ms.getEntryName(), ex); return; } Entity en = mechFileParser.getEntity(); @@ -672,7 +672,15 @@ public void purchaseShipSearchResult() { : calculatePartTransitTime(Compute.d6(2) - 2); getFinances().debit(TransactionType.UNIT_PURCHASE, getLocalDate(), cost, "Purchased " + en.getShortName()); - addNewUnit(en, true, transitDays, 3); + + int quality = 3; + + if (campaignOptions.isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } + + addNewUnit(en, true, transitDays, quality); + if (!getCampaignOptions().isInstantUnitMarketDelivery()) { addReport("Unit will be delivered in " + transitDays + " days."); } diff --git a/MekHQ/src/mekhq/campaign/Quartermaster.java b/MekHQ/src/mekhq/campaign/Quartermaster.java index adf4878033..f0b6e9d378 100644 --- a/MekHQ/src/mekhq/campaign/Quartermaster.java +++ b/MekHQ/src/mekhq/campaign/Quartermaster.java @@ -466,17 +466,26 @@ public void arrivePart(Part part) { public boolean buyUnit(Entity en, int days) { Objects.requireNonNull(en); + int quality = 3; + + if (campaign.getCampaignOptions().isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } + if (getCampaignOptions().isPayForUnits()) { Money cost = new Unit(en, getCampaign()).getBuyCost(); if (getCampaign().getFinances().debit(TransactionType.UNIT_PURCHASE, getCampaign().getLocalDate(), cost, "Purchased " + en.getShortName())) { - getCampaign().addNewUnit(en, false, days); + + getCampaign().addNewUnit(en, false, days, quality); + return true; } else { return false; } } else { - getCampaign().addNewUnit(en, false, days); + + getCampaign().addNewUnit(en, false, days, quality); return true; } } diff --git a/MekHQ/src/mekhq/campaign/mission/AtBContract.java b/MekHQ/src/mekhq/campaign/mission/AtBContract.java index 606472d2e4..6ea6a33a57 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBContract.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBContract.java @@ -510,23 +510,35 @@ public void doBonusRoll(Campaign c) { rat = "CivilianUnits_PrimMech"; c.addReport("Bonus: civilian Mek"); break; + default: + throw new IllegalStateException("Unexpected value in mekhq/campaign/mission/AtBContract.java/doBonusRoll: " + roll); } if (null != rat) { Entity en = null; RandomUnitGenerator.getInstance().setChosenRAT(rat); ArrayList msl = RandomUnitGenerator.getInstance().generate(1); + + int quality = 3; + + if (c.getCampaignOptions().isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } + if (!msl.isEmpty() && (msl.get(0) != null)) { try { en = new MechFileParser(msl.get(0).getSourceFile(), msl.get(0).getEntryName()).getEntity(); } catch (EntityLoadingException ex) { - LogManager.getLogger().error("Unable to load entity: " + msl.get(0).getSourceFile() - + ": " + msl.get(0).getEntryName() + ": " + ex.getMessage(), ex); + LogManager.getLogger().error("Unable to load entity: {}: {}: {}", + msl.get(0).getSourceFile(), + msl.get(0).getEntryName(), + ex.getMessage(), + ex); } } if (null != en) { - c.addNewUnit(en, false, 0); + c.addNewUnit(en, false, 0, quality); } else { c.addReport("Could not load unit"); } diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java index 3d952538d0..7f05780927 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java @@ -27,6 +27,7 @@ import megamek.common.MechSummaryCache; import mekhq.campaign.Campaign; import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.unit.Unit; import mekhq.utilities.MHQXMLUtility; import org.apache.logging.log4j.LogManager; import org.w3c.dom.Node; @@ -46,7 +47,7 @@ public class AddUnitStoryTrigger extends StoryTrigger { protected void execute() { MechSummary ms = MechSummaryCache.getInstance().getMech(entityName); if (ms == null) { - LogManager.getLogger().error("Cannot find entry for " + entityName); + LogManager.getLogger().error("Cannot find entry for {}", entityName); return; } @@ -54,11 +55,19 @@ protected void execute() { try { mechFileParser = new MechFileParser(ms.getSourceFile(), ms.getEntryName()); } catch (Exception ex) { - LogManager.getLogger().error("Unable to load unit: " + ms.getEntryName(), ex); + LogManager.getLogger().error("Unable to load unit: {}", ms.getEntryName(), ex); return; } + Entity en = mechFileParser.getEntity(); - getCampaign().addNewUnit(en, false, 0); + + int quality = 3; + + if (getCampaign().getCampaignOptions().isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } + + getCampaign().addNewUnit(en, false, 0, quality); } @Override diff --git a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java index bbac822218..6f50905079 100644 --- a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java +++ b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java @@ -942,16 +942,34 @@ private void generateEntity(final Campaign campaign, private List createUnits(final Campaign campaign, final List trackers) { final List units = new ArrayList<>(); + for (final CompanyGenerationPersonTracker tracker : trackers) { if (tracker.getEntity() == null) { continue; } - final Unit unit = campaign.addNewUnit(tracker.getEntity(), false, 0); + int quality = 3; + + if (campaign.getCampaignOptions().isUseRandomUnitQualities()) { + int modifier = 0; + + if (tracker.getPerson().isCommander()) { + modifier = 2; + } else if (tracker.getPerson().getRank().isOfficer()) { + modifier = 1; + } + + quality = Unit.getRandomUnitQuality(modifier); + } + + final Unit unit = campaign.addNewUnit(tracker.getEntity(), false, 0, quality); + unit.addPilotOrSoldier(tracker.getPerson()); + if (getOptions().isGenerateUnitsAsAttached()) { tracker.getPerson().setOriginalUnit(unit); } + units.add(unit); } return units; @@ -1286,8 +1304,16 @@ public List generateMothballedEntities(final Campaign campaign, */ private List createMothballedSpareUnits(final Campaign campaign, final List mothballedEntities) { + int quality; + + if (campaign.getCampaignOptions().isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } else { + quality = 3; + } + final List mothballedUnits = mothballedEntities.stream() - .map(entity -> campaign.addNewUnit(entity, false, 0)) + .map(entity -> campaign.addNewUnit(entity, false, 0, quality)) .collect(Collectors.toList()); mothballedUnits.forEach(Unit::completeMothball); return mothballedUnits; diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java index ac62cb4204..0796ccaee9 100644 --- a/MekHQ/src/mekhq/gui/CampaignGUI.java +++ b/MekHQ/src/mekhq/gui/CampaignGUI.java @@ -1890,10 +1890,17 @@ private File checkFileEnding(File file, String format) { protected void loadListFile(final boolean allowNewPilots) { final File unitFile = FileDialogs.openUnits(getFrame()).orElse(null); + + int quality = 3; + + if (getCampaign().getCampaignOptions().isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } + if (unitFile != null) { try { for (Entity entity : new MULParser(unitFile, getCampaign().getGameOptions()).getEntities()) { - getCampaign().addNewUnit(entity, allowNewPilots, 0); + getCampaign().addNewUnit(entity, allowNewPilots, 0, quality); } } catch (Exception e) { LogManager.getLogger().error("", e); diff --git a/MekHQ/src/mekhq/gui/adapter/ProcurementTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/ProcurementTableMouseAdapter.java index a633ed44fc..b7a480fefa 100644 --- a/MekHQ/src/mekhq/gui/adapter/ProcurementTableMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/ProcurementTableMouseAdapter.java @@ -22,6 +22,7 @@ import mekhq.MekHQ; import mekhq.campaign.event.ProcurementEvent; import mekhq.campaign.parts.Part; +import mekhq.campaign.unit.Unit; import mekhq.campaign.work.IAcquisitionWork; import mekhq.gui.CampaignGUI; import mekhq.gui.model.ProcurementTableModel; @@ -196,9 +197,17 @@ private void addOneItem(final IAcquisitionWork acquisition) { if (equipment instanceof Part) { gui.getCampaign().getQuartermaster().addPart((Part) equipment, 0); } else if (equipment instanceof Entity) { - gui.getCampaign().addNewUnit((Entity) equipment, false, 0); + int quality; + + if (gui.getCampaign().getCampaignOptions().isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } else { + quality = 3; + } + + gui.getCampaign().addNewUnit((Entity) equipment, false, 0, quality); } else { - LogManager.getLogger().error("Attempted to add unknown equipment of " + acquisition.getAcquisitionName()); + LogManager.getLogger().error("Attempted to add unknown equipment of {}", acquisition.getAcquisitionName()); return; } diff --git a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java index bca9b91e87..14f94a9df2 100644 --- a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java @@ -1362,7 +1362,17 @@ private void addRATRolledUnit() { } if (getLastRolledUnit() != null) { - final Unit unit = getGUI().getCampaign().addNewUnit(getLastRolledUnit(), false, 0); + int quality; + + if (getGUI().getCampaign().getCampaignOptions().isUseRandomUnitQualities()) { + quality = Unit.getRandomUnitQuality(0); + } else { + quality = 3; + } + + final Unit unit = getGUI().getCampaign().addNewUnit(getLastRolledUnit(), false, 0, quality); + + if ((getPerson() != null) && (getPerson().getUnit() == null)) { unit.addPilotOrSoldier(getPerson()); getPerson().setOriginalUnit(unit); diff --git a/MekHQ/src/mekhq/gui/dialog/MekHQUnitSelectorDialog.java b/MekHQ/src/mekhq/gui/dialog/MekHQUnitSelectorDialog.java index 66bc8e4cac..1e42c34685 100644 --- a/MekHQ/src/mekhq/gui/dialog/MekHQUnitSelectorDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/MekHQUnitSelectorDialog.java @@ -124,7 +124,13 @@ protected JPanel createButtonsPanel() { protected void select(boolean isGM) { if (getSelectedEntity() != null) { if (isGM) { - campaign.addNewUnit(selectedUnit.getEntity(), false, 0); + int quality = 3; + + if (campaign.getCampaignOptions().isUseRandomUnitQualities()) { + quality = UnitOrder.getRandomUnitQuality(0); + } + + campaign.addNewUnit(selectedUnit.getEntity(), false, 0, quality); } else { campaign.getShoppingList().addShoppingItem(selectedUnit, 1, campaign); } diff --git a/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java b/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java index e88cb10c0c..0a706eb834 100644 --- a/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java @@ -31,6 +31,7 @@ import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.PersonnelRole; import mekhq.campaign.unit.Unit; +import mekhq.campaign.unit.UnitOrder; import mekhq.campaign.unit.actions.HirePersonnelUnitAction; import mekhq.gui.CampaignGUI; import mekhq.gui.enums.PersonnelFilter; @@ -374,7 +375,15 @@ private void addUnit(Entity en, boolean pay) { unitCost, "Purchased " + en.getShortName())) { return; } - Unit unit = campaign.addNewUnit(en, false, 0); + + int quality = 3; + + if (campaign.getCampaignOptions().isUseRandomUnitQualities()) { + quality = UnitOrder.getRandomUnitQuality(0); + } + + Unit unit = campaign.addNewUnit(en, false, 0, quality); + if (unit == null) { // No such unit matching the entity. return; diff --git a/MekHQ/unittests/mekhq/campaign/QuartermasterTest.java b/MekHQ/unittests/mekhq/campaign/QuartermasterTest.java index d1c819ab65..f65bcb50da 100644 --- a/MekHQ/unittests/mekhq/campaign/QuartermasterTest.java +++ b/MekHQ/unittests/mekhq/campaign/QuartermasterTest.java @@ -248,7 +248,7 @@ public void buyUnitAddsUnconditionallyIfNotPayingForUnits() { assertTrue(quartermaster.buyUnit(mockEntity, transitDays)); // ...and the new unit should be added to the campaign. - verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(transitDays)); + verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(transitDays), eq(3)); } @Test @@ -301,7 +301,7 @@ public void buyUnitBuysAUnitIfWeCanAffordIt() { assertTrue(quartermaster.buyUnit(mockEntity, 0)); // ...and the new unit should be added to the campaign... - verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0)); + verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0), eq(3)); // ...and it should cost the right amount. assertEquals(Money.of(cost), captor.getValue()); @@ -332,7 +332,7 @@ public void buyUnitBuysInfantryUsingAlternateCost() { assertTrue(quartermaster.buyUnit(mockEntity, 0)); // ...and the new infantry should be added to the campaign... - verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0)); + verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0), eq(3)); // ...and it should cost the right amount. assertEquals(Money.of(cost), captor.getValue()); @@ -368,7 +368,7 @@ public void buyUnitAppliesClanCostMultiplier() { assertTrue(quartermaster.buyUnit(mockEntity, 0)); // ...and the new unit should be added to the campaign... - verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0)); + verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0), eq(3)); // ...and it should cost the right amount. assertEquals(Money.of(clanMultiplier * cost), captor.getValue()); @@ -404,7 +404,7 @@ public void buyUnitAppliesClanCostMultiplierToInfantryAlso() { assertTrue(quartermaster.buyUnit(mockEntity, 0)); // ...and the new clan infantry should be added to the campaign... - verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0)); + verify(mockCampaign, times(1)).addNewUnit(eq(mockEntity), eq(false), eq(0), eq(3)); // ...and it should cost the right amount. assertEquals(Money.of(clanMultiplier * cost), captor.getValue());