diff --git a/MekHQ/resources/mekhq/resources/AutoResolveMethod.properties b/MekHQ/resources/mekhq/resources/AutoResolveMethod.properties
new file mode 100644
index 0000000000..68926b8819
--- /dev/null
+++ b/MekHQ/resources/mekhq/resources/AutoResolveMethod.properties
@@ -0,0 +1,6 @@
+AutoResolveMethod.PRINCESS.text=Princess
+AutoResolveMethod.PRINCESS.toolTipText=Princess
+AutoResolveMethod.UNITS_MATTER.text=Units Matter
+AutoResolveMethod.UNITS_MATTER.toolTipText=Units Matter
+AutoResolveMethod.ABSTRACT_COMBAT.text=Abstract Combat
+AutoResolveMethod.ABSTRACT_COMBAT.toolTipText=Abstract Combat
\ No newline at end of file
diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
index 0d13950089..4b090f1a05 100644
--- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
+++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
@@ -890,6 +890,8 @@ chkUseStratCon.text=Use StratCon campaign rules
chkUseStratCon.toolTipText=An update of the AtB ruleset.
lblSkillLevel.text=Skill Level
lblSkillLevel.toolTipText=This is the difficulty level for generated scenarios.
Values above Elite are not recommended.
+lblAutoResolveType.text=Auto Resolve method:
+lblAutoResolveType.toolTipText=Auto resolve to use in campaign play.
Princess: The bot plays the MM game in your place.
Units Matter: A very fast simulation focused on speed.
Abstract Combat: Complex simulation well suited for very large confrontations.
lblScenarioMod.text=Random Scenario Modifiers
lblScenarioModMax.text=Maximum:
lblScenarioModMax.toolTipText=This is the maximum number of random scenario mods that can spawn on for a single Scenario. Excludes StratCon facility modifiers.
@@ -966,8 +968,11 @@ chkRegionalMekVariations.text=Varied weight distributions by faction
chkRegionalMekVariations.toolTipText=Use alternate weight class distributions for some factions.
chkAttachedPlayerCamouflage.text=Player-controlled allied units use player's camouflage
chkPlayerControlsAttachedUnits.text=All attached allied units are player controlled
-chkUseBotControlledAutoResolve.text=Bots play auto resolve
-chkUseBotControlledAutoResolve.toolTipText=If checked, auto resolve will open a game and add all your units to a bot on your team, otherwise, auto resolve will use Abstract Combat System to resolve the scenarios.
+chkUseBotControlledAutoResolveAARC.text=Auto Resolve using Abstract Auto Resolve Combat
+chkUseBotControlledAutoResolve.text=Auto Resolve using Bots
+chkUseBotControlledAutoResolve.toolTipText=If checked, auto resolve will open a game and add all your units to a bot on your team, otherwise, auto resolve will use Abstract Auto Resolve Combat to resolve the scenarios.
+chkAutoResolveVictoryChanceEnabled.text=Show auto resolve victory chance
+chkAutoResolveVictoryChanceEnabled.toolTipText=If checked, the pre-auto resolve dialog will show the chance of victory for the player. Only works when using Abstract Auto Resolve Combat.
chkUseWeatherConditions.text=Use weather conditions
chkUseWeatherConditions.toolTipText=Generate weather conditions when generating a scenario.
chkUseLightConditions.text=Use light conditions
diff --git a/MekHQ/src/mekhq/MekHQ.java b/MekHQ/src/mekhq/MekHQ.java
index 4584159393..64fa7811da 100644
--- a/MekHQ/src/mekhq/MekHQ.java
+++ b/MekHQ/src/mekhq/MekHQ.java
@@ -48,7 +48,6 @@
import mekhq.campaign.ResolveScenarioTracker;
import mekhq.campaign.ResolveScenarioTracker.PersonStatus;
import mekhq.campaign.autoResolve.AutoResolveEngine;
-import mekhq.campaign.autoResolve.AutoResolveGame;
import mekhq.campaign.autoResolve.AutoResolveMethod;
import mekhq.campaign.autoResolve.helper.AutoResolveClient;
import mekhq.campaign.autoResolve.scenarioResolver.components.AutoResolveConcludedEvent;
@@ -80,9 +79,10 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.ObjectInputFilter.Config;
-import java.util.HashMap;
+import java.util.*;
import java.util.List;
-import java.util.UUID;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
/**
@@ -527,6 +527,7 @@ public void gamePhaseChange(GamePhaseChangeEvent e) {
// Why Empty?
}
+ // TODO: LUANA
public void autoResolveConcluded(AutoResolveConcludedEvent autoResolveConcludedEvent){
try {
String message = autoResolveConcludedEvent.controlledScenario() ?
@@ -693,11 +694,15 @@ public void gameVictory(PostGameResolution gve) {
final File tempImageDirectory = new File("data/images/temp");
if (tempImageDirectory.isDirectory()) {
// This can't be null because of the above
- Stream.of(tempImageDirectory.listFiles()).filter(file -> file.getName().endsWith(".png"))
- .forEach(File::delete);
+ var totalDeletedFiles = Stream.of(Objects.requireNonNull(tempImageDirectory.listFiles()))
+ .filter(file -> file.getName().endsWith(".png"))
+ .map(File::delete)
+ .mapToInt(result -> result ? 1 : 0)
+ .sum();
+ logger.info("Deleted {} temporary image files", totalDeletedFiles);
}
} catch (Exception ex) {
- logger.error(ex, "gameVictory()");
+ logger.error("Exception during gameVictory() run", ex);
}
}
@@ -802,7 +807,60 @@ public static void updateGuiScaling() {
public void startAutoResolve(AtBScenario scenario, List units) {
currentScenario = scenario;
- new AutoResolveEngine(AutoResolveMethod.ABSTRACT_COMBAT_SYSTEM).resolveBattle(this, units, scenario);
+ String message = "This will auto resolve the battle. Do you want to proceed?";
+ var autoResolveMethod = getCampaign().getCampaignOptions().getAutoResolveMethod();
+ if (getCampaign().getCampaignOptions().isAutoResolveVictoryChanceEnabled()
+ // unfortunately UNITS MATTER force creating has a bug that makes it impossible to calculate victory chance without causing
+ // irreversible changes to the campaign
+ && autoResolveMethod.equals(AutoResolveMethod.ABSTRACT_COMBAT)) {
+
+ var percent = calculateVictoryChance(scenario, units);
+ message = "Your chance of victory in this combat is " + percent + "%, do you want to proceed?";
+ }
+ String title = "Auto Resolve Battle";
+ boolean proceed = JOptionPane.showConfirmDialog(campaignGUI.getFrame(), message, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION;
+
+ if (proceed) {
+ new AutoResolveEngine(autoResolveMethod)
+ .resolveBattle(this, units, scenario, this::autoResolveConcluded);
+ }
+ }
+
+ /**
+ * Calculates the victory chance for a given scenario and list of units by running multiple auto resolve scenarios in parallel.
+ *
+ * @param scenario the scenario to resolve
+ * @param units the list of units involved in the scenario
+ * @return the calculated victory chance as an integer percentage (0 to 100)
+ */
+ private int calculateVictoryChance(AtBScenario scenario, List units) {
+ var atomicInt = new AtomicInteger(0);
+ int numTasks = 50;
+ ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+ List> futures = new ArrayList<>();
+
+ for (int i = 0; i < numTasks; i++) {
+ futures.add(executor.submit(() -> {
+ new AutoResolveEngine(AutoResolveMethod.ABSTRACT_COMBAT)
+ .resolveBattle(this, units, scenario, r -> {
+ if (r.controlledScenario()) {
+ atomicInt.incrementAndGet();
+ }
+ });
+ }));
+ }
+
+ // Wait for all tasks to complete
+ for (Future> future : futures) {
+ try {
+ future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error in parallel execution", e);
+ }
+ }
+
+ executor.shutdown();
+ return atomicInt.get() * 2;
}
private static class MekHqPropertyChangedListener implements PropertyChangeListener {
diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java
index bee8e940cf..4ec82a9c37 100644
--- a/MekHQ/src/mekhq/campaign/CampaignOptions.java
+++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java
@@ -27,6 +27,7 @@
import megamek.logging.MMLogger;
import mekhq.MekHQ;
import mekhq.Utilities;
+import mekhq.campaign.autoResolve.AutoResolveMethod;
import mekhq.campaign.enums.PlanetaryAcquisitionFactionLimit;
import mekhq.campaign.finances.Money;
import mekhq.campaign.finances.enums.FinancialYearDuration;
@@ -600,7 +601,8 @@ public static String getTransitUnitName(final int unit) {
private int scenarioModChance;
private int scenarioModBV;
private boolean autoConfigMunitions;
- private boolean princessBotAutoResolve;
+ private AutoResolveMethod autoResolveMethod;
+ private boolean autoResolveVictoryChanceEnabled;
// endregion Against the Bot Tab
// endregion Variable Declarations
@@ -1191,7 +1193,8 @@ public CampaignOptions() {
useAtB = false;
useStratCon = false;
setSkillLevel(SkillLevel.REGULAR);
- princessBotAutoResolve = true;
+ autoResolveMethod = AutoResolveMethod.PRINCESS;
+ autoResolveVictoryChanceEnabled = false;
// Unit Administration
useAero = false;
@@ -5163,7 +5166,8 @@ public void writeToXml(final PrintWriter pw, int indent) {
// region AtB Tab
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "skillLevel", getSkillLevel().name());
- MHQXMLUtility.writeSimpleXMLTag(pw, indent, "princessBotAutoResolve", isPrincessBotAutoResolve());
+ MHQXMLUtility.writeSimpleXMLTag(pw, indent, "autoResolveMethod", getAutoResolveMethod().name());
+ MHQXMLUtility.writeSimpleXMLTag(pw, indent, "autoResolveVictoryChanceEnabled", isAutoResolveVictoryChanceEnabled());
// endregion AtB Tab
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "phenotypeProbabilities", phenotypeProbabilities);
@@ -6148,8 +6152,10 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve
// region AtB Tab
} else if (wn2.getNodeName().equalsIgnoreCase("skillLevel")) {
retVal.setSkillLevel(SkillLevel.valueOf(wn2.getTextContent().trim()));
- } else if (wn2.getNodeName().equalsIgnoreCase("princessBotAutoResolve")) {
- retVal.setPrincessBotAutoResolve(Boolean.parseBoolean(wn2.getTextContent().trim()));
+ } else if (wn2.getNodeName().equalsIgnoreCase("autoResolveMethod")) {
+ retVal.setAutoResolveMethod(AutoResolveMethod.valueOf(wn2.getTextContent().trim()));
+ } else if (wn2.getNodeName().equalsIgnoreCase("autoResolveVictoryChanceEnabled")) {
+ retVal.setAutoResolveVictoryChanceEnabled(Boolean.parseBoolean(wn2.getTextContent().trim()));
// endregion AtB Tab
} else if (wn2.getNodeName().equalsIgnoreCase("phenotypeProbabilities")) {
@@ -6424,12 +6430,20 @@ public void migrateMarriageSurnameWeights47(final String... values) {
}
}
- public boolean isPrincessBotAutoResolve() {
- return princessBotAutoResolve;
+ public AutoResolveMethod getAutoResolveMethod() {
+ return autoResolveMethod;
}
- public void setPrincessBotAutoResolve(final boolean princessBotAutoResolve) {
- this.princessBotAutoResolve = princessBotAutoResolve;
+ public void setAutoResolveMethod(final AutoResolveMethod autoResolveMethod) {
+ this.autoResolveMethod = autoResolveMethod;
+ }
+
+ public boolean isAutoResolveVictoryChanceEnabled() {
+ return autoResolveVictoryChanceEnabled;
+ }
+
+ public void setAutoResolveVictoryChanceEnabled(final boolean autoResolveVictoryChanceEnabled) {
+ this.autoResolveVictoryChanceEnabled = autoResolveVictoryChanceEnabled;
}
// endregion File IO
diff --git a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java
index 7f444d57ee..7f45693f66 100644
--- a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java
+++ b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java
@@ -14,10 +14,15 @@
package mekhq.campaign.autoResolve;
import mekhq.MekHQ;
+import mekhq.campaign.autoResolve.scenarioResolver.components.AutoResolveConcludedEvent;
import mekhq.campaign.mission.AtBScenario;
import mekhq.campaign.unit.Unit;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
/**
* @author Luana Coppio
@@ -30,11 +35,11 @@ public AutoResolveEngine(AutoResolveMethod method) {
this.autoResolveMethod = method;
}
- public void resolveBattle(MekHQ app, List units, AtBScenario scenario) {
+ public void resolveBattle(MekHQ app, List units, AtBScenario scenario, Consumer autoResolveConcludedEvent) {
var scenarioSpecificResolutionResolver = autoResolveMethod.of(scenario);
var game = new AutoResolveGame(app, units, scenario);
var result = scenarioSpecificResolutionResolver.resolveScenario(game);
- app.autoResolveConcluded(result);
+ autoResolveConcludedEvent.accept(result);
}
}
diff --git a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java
index 3c29b96e1b..ba96b29060 100644
--- a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java
+++ b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java
@@ -13,35 +13,78 @@
*/
package mekhq.campaign.autoResolve;
+import megamek.MegaMek;
+import mekhq.MekHQ;
import mekhq.campaign.autoResolve.scenarioResolver.ScenarioResolver;
import mekhq.campaign.autoResolve.scenarioResolver.abstractCombatSystem.AcsSimpleScenarioResolver;
import mekhq.campaign.autoResolve.scenarioResolver.unitsMatter.UnitsMatterSimpleScenarioResolver;
import mekhq.campaign.mission.AtBScenario;
+import java.util.Optional;
+import java.util.ResourceBundle;
+
/**
* @author Luana Coppio
*/
public enum AutoResolveMethod {
- UNITS_MATTER(){
+ PRINCESS("AutoResolveMethod.PRINCESS.text", "AutoResolveMethod.PRINCESS.toolTipText") {
+ @Override
+ public ScenarioResolver of(AtBScenario scenario) {
+ throw new UnsupportedOperationException("Princess method not implemented");
+ }
+ },
+ UNITS_MATTER("AutoResolveMethod.UNITS_MATTER.text", "AutoResolveMethod.UNITS_MATTER.toolTipText") {
@Override
public ScenarioResolver of(AtBScenario scenario) {
return new UnitsMatterSimpleScenarioResolver(scenario);
}
},
- ABSTRACT_COMBAT_SYSTEM() {
+ ABSTRACT_COMBAT("AutoResolveMethod.ABSTRACT_COMBAT.text", "AutoResolveMethod.ABSTRACT_COMBAT.toolTipText") {
@Override
public ScenarioResolver of(AtBScenario scenario) {
return new AcsSimpleScenarioResolver(scenario);
}
};
- public static AutoResolveMethod fromString(String method) {
+ private final String name;
+ private final String toolTipText;
+
+ AutoResolveMethod(final String name, final String toolTipText) {
+ final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.AutoResolveMethod",
+ MekHQ.getMHQOptions().getLocale());
+ this.name = resources.getString(name);
+ this.toolTipText = resources.getString(toolTipText);
+ }
+
+ public String getToolTipText() {
+ return toolTipText;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static Optional fromInteger(int index) {
+ if (index < 0 || index >= values().length) {
+ return Optional.empty();
+ }
+ return Optional.of(values()[index]);
+ }
+
+ public static Optional fromString(String method) {
return switch (method) {
- case "UNITS_MATTER" -> UNITS_MATTER;
- case "ABSTRACT_COMBAT_SYSTEM" -> ABSTRACT_COMBAT_SYSTEM;
- default -> throw new IllegalArgumentException("Invalid method: " + method);
+ case "PRINCESS" -> Optional.of(PRINCESS);
+ case "UNITS_MATTER" -> Optional.of(UNITS_MATTER);
+ case "ABSTRACT_COMBAT_SYSTEM" -> Optional.of(ABSTRACT_COMBAT);
+ default -> Optional.empty();
};
}
public abstract ScenarioResolver of(AtBScenario scenario);
+
+ @Override
+ public String toString() {
+ return name;
+ }
}
+
diff --git a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java
index 88663657eb..ec573ca0d6 100644
--- a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java
+++ b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java
@@ -166,8 +166,7 @@ private void setupPlayerForces(Campaign campaign, List units, AtBScenario
if (force != null) {
entity.setForceString(force.getFullMMName());
}
-
- var newCrewRef = getNewCrewRef(unit);
+ var newCrewRef = getNewCrewRef(unit.getEntity().getCrew());
entity.setCrew(newCrewRef);
entities.add(entity);
}
@@ -202,8 +201,8 @@ private void setupPlayerForces(Campaign campaign, List units, AtBScenario
sendEntities(entities);
}
- private static Crew getNewCrewRef(Unit unit) {
- var originalCrew = unit.getEntity().getCrew();
+ public static Crew getNewCrewRef(Crew originalCrew) {
+
var newCrewRef = new Crew(originalCrew.getCrewType(), originalCrew.getName(), originalCrew.getSize(),
originalCrew.getGunnery(), originalCrew.getPiloting(), originalCrew.getGender(), originalCrew.isClanPilot(),
originalCrew.getExtraData());
@@ -282,9 +281,19 @@ private void setupBotEntities(Player bot, BotForce botForce) {
String forceName = bot.getName() + "|1";
var entities = new ArrayList();
botForce.generateRandomForces(units, campaign);
- for (Entity entity : botForce.getFullEntityList(campaign)) {
+ for (Entity originalBotEntity : botForce.getFullEntityList(campaign)) {
+ var entity = ASConverter.getUndamagedEntity(originalBotEntity);
+ if (entity == null) {
+ logger.warn("Could not convert entity for bot {} - {}", bot.getName(), originalBotEntity);
+ continue;
+ }
+
entity.setOwner(bot);
entity.setForceString(forceName);
+ entity.setCrew(getNewCrewRef(entity.getCrew()));
+ entity.setId(originalBotEntity.getId());
+ entity.setExternalIdAsString(originalBotEntity.getExternalIdAsString());
+ entity.setCommander(originalBotEntity.isCommander());
if (entity.getDeployRound() == 0) {
entity.setDeployRound(botForce.getDeployRound());
diff --git a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java
index ca1352bc09..4ba498ef8d 100644
--- a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java
+++ b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java
@@ -2,19 +2,17 @@
import megamek.client.generator.RandomCallsignGenerator;
import megamek.common.*;
-import mekhq.MekHQ;
+import megamek.common.alphaStrike.conversion.ASConverter;
+import megamek.common.annotations.Nullable;
import mekhq.campaign.Campaign;
import mekhq.campaign.autoResolve.scenarioResolver.components.AutoResolveForce;
-
-import mekhq.campaign.mission.AtBContract;
-import mekhq.campaign.mission.AtBScenario;
-import mekhq.campaign.mission.BotForce;
-import mekhq.campaign.mission.Scenario;
+import mekhq.campaign.mission.*;
import mekhq.campaign.unit.Unit;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
+import static mekhq.campaign.autoResolve.helper.SetupForces.getNewCrewRef;
import static mekhq.campaign.force.StrategicFormation.getStandardForceSize;
public class SetupTeams {
@@ -44,7 +42,38 @@ static private List getBotForces(Campaign campaign, List
}
static private AutoResolveForce playerForce(int playerID, String forceName, List units) {
- return new AutoResolveForce(1, forceName, playerID, units.stream().map(Unit::getEntity).toList());
+ return new AutoResolveForce(1, forceName, playerID, units.stream().map(SetupTeams::breakEntityRef).filter(Objects::nonNull).toList());
+ }
+
+ @Nullable
+ public static Entity breakEntityRef(Unit unit) {
+ var entity = ASConverter.getUndamagedEntity(unit.getEntity());
+ // Set the TempID for auto reporting
+ if (Objects.isNull(entity)) {
+ return null;
+ }
+
+ entity.setExternalIdAsString(unit.getId().toString());
+ // Set the owner
+ entity.setOwner(unit.getCampaign().getPlayer());
+
+ // If this unit is a spacecraft, set the crew size and marine size values
+ if (entity.isLargeCraft() || (entity.getUnitType() == UnitType.SMALL_CRAFT)) {
+ entity.setNCrew(unit.getActiveCrew().size());
+ entity.setNMarines(unit.getMarineCount());
+ }
+ // Calculate deployment round
+ int deploymentRound = entity.getDeployRound();
+
+ entity.setDeployRound(deploymentRound);
+ var force = unit.getCampaign().getForceFor(unit);
+ if (force != null) {
+ entity.setForceString(force.getFullMMName());
+ }
+ var newCrewRef = getNewCrewRef(unit.getEntity().getCrew());
+ entity.setCrew(newCrewRef);
+
+ return entity;
}
static private List setupBotEntities(Campaign campaign, List units, BotForce botForce, Scenario scenario, int forceID) {
@@ -74,12 +103,18 @@ static private List setupBotEntities(Campaign campaign, List units
comp = comp.thenComparing(((Entity e) -> e.getRole().toString()));
entitiesSorted.sort(comp);
- for (Entity entity : entitiesSorted) {
+ for (Entity originalEntity : entitiesSorted) {
+ if (null == originalEntity) {
+ continue;
+ }
+ var entity = ASConverter.getUndamagedEntity(originalEntity);
if (null == entity) {
continue;
}
entity.setForceId(forceID);
entity.setOwner(player);
+ entity.setCrew(getNewCrewRef(originalEntity.getCrew()));
+ entity.setDeployRound(originalEntity.getDeployRound());
if ((i != 0)
&& !lastType.equals(Entity.getEntityMajorTypeName(entity.getEntityType()))) {
forceIdLance++;
@@ -91,6 +126,7 @@ static private List setupBotEntities(Campaign campaign, List units
String fName = String.format(forceName, lanceName, forceIdLance);
entity.setForceString(fName);
entity.setDestroyed(false);
+
entities.add(entity);
i++;
if (entity instanceof GunEmplacement gun) {
diff --git a/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java b/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java
index a4ce03ded4..d37f9af6aa 100644
--- a/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java
+++ b/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java
@@ -33,8 +33,9 @@ protected ScenarioResolver(AtBScenario scenario) {
public static ScenarioResolver of(AutoResolveMethod method, AtBScenario scenario) {
return switch (method) {
+ case PRINCESS -> throw new UnsupportedOperationException("Princess method is not run here!");
case UNITS_MATTER -> new UnitsMatterSimpleScenarioResolver(scenario);
- case ABSTRACT_COMBAT_SYSTEM -> new AcsSimpleScenarioResolver(scenario);
+ case ABSTRACT_COMBAT -> new AcsSimpleScenarioResolver(scenario);
};
}
diff --git a/MekHQ/src/mekhq/gui/BriefingTab.java b/MekHQ/src/mekhq/gui/BriefingTab.java
index eabe391d8c..a0bcd42608 100644
--- a/MekHQ/src/mekhq/gui/BriefingTab.java
+++ b/MekHQ/src/mekhq/gui/BriefingTab.java
@@ -36,7 +36,6 @@
import mekhq.campaign.Kill;
import mekhq.campaign.ResolveScenarioTracker;
import mekhq.campaign.ResolveScenarioTracker.PersonStatus;
-import mekhq.campaign.autoResolve.AutoResolveEngine;
import mekhq.campaign.event.*;
import mekhq.campaign.finances.Money;
import mekhq.campaign.finances.enums.TransactionType;
@@ -871,11 +870,10 @@ private void autoResolveScenario() {
if (scenario == null) {
return;
}
- if (getCampaignOptions().isPrincessBotAutoResolve()) {
- startScenario(getCampaign().getAutoResolveBehaviorSettings());
- } else {
- getCampaignGui().getApplication()
+ switch(getCampaignOptions().getAutoResolveMethod()) {
+ case ABSTRACT_COMBAT, UNITS_MATTER-> getCampaignGui().getApplication()
.startAutoResolve((AtBScenario) scenario, playerUnits(scenario, new StringBuilder()));
+ case PRINCESS -> startScenario(getCampaign().getAutoResolveBehaviorSettings());
}
}
diff --git a/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java b/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java
index dfac268d74..72ddd79839 100644
--- a/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java
@@ -1642,10 +1642,12 @@ private void finish() {
StratconRulesManager.processScenarioCompletion(tracker);
aborted = false;
this.setVisible(false);
+ dispose();
}
private void cancel() {
setVisible(false);
+ dispose();
}
// region Misc II
diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
index 264a380d5b..80a882f387 100644
--- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
+++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
@@ -43,6 +43,7 @@
import mekhq.campaign.CampaignOptions;
import mekhq.campaign.CampaignPreset;
import mekhq.campaign.RandomSkillPreferences;
+import mekhq.campaign.autoResolve.AutoResolveMethod;
import mekhq.campaign.enums.PlanetaryAcquisitionFactionLimit;
import mekhq.campaign.event.OptionsChangedEvent;
import mekhq.campaign.finances.enums.FinancialYearDuration;
@@ -647,6 +648,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane {
private JCheckBox chkUseAtB;
private JCheckBox chkUseStratCon;
private MMComboBox comboSkillLevel;
+ private MMComboBox comboAutoResolveType;
// unit administration
private JCheckBox chkUseAero;
@@ -688,7 +690,8 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane {
private JCheckBox chkRegionalMekVariations;
private JCheckBox chkAttachedPlayerCamouflage;
private JCheckBox chkPlayerControlsAttachedUnits;
- private JCheckBox chkUseBotControlledAutoResolve;
+
+ private JCheckBox chkAutoResolveVictoryChanceEnabled;
private JCheckBox chkUseDropShips;
private JCheckBox chkUseWeatherConditions;
private JCheckBox chkUseLightConditions;
@@ -3364,14 +3367,31 @@ private JScrollPane createAgainstTheBotTab() {
gridBagConstraints.gridy = yTablePosition++;
panSubAtBScenario.add(chkPlayerControlsAttachedUnits, gridBagConstraints);
- chkUseBotControlledAutoResolve = new JCheckBox(
- resources.getString("chkUseBotControlledAutoResolve.text"));
- chkUseBotControlledAutoResolve.setToolTipText(resources.getString("chkUseBotControlledAutoResolve.toolTipText"));
+ JLabel lblAutoResolveType = new JLabel(resources.getString("lblAutoResolveType.text"));
+ gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = yTablePosition++;
- panSubAtBScenario.add(chkUseBotControlledAutoResolve, gridBagConstraints);
+ gridBagConstraints.gridwidth = 1;
+ panSubAtBScenario.add(lblAutoResolveType, gridBagConstraints);
+
+ final DefaultComboBoxModel autoResolveTypeModel = new DefaultComboBoxModel<>(
+ AutoResolveMethod.values());
+ comboAutoResolveType = new MMComboBox<>("comboAutoResolveType", autoResolveTypeModel);
+ comboAutoResolveType.setToolTipText(resources.getString("lblAutoResolveType.toolTipText"));
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = yTablePosition;
+ panSubAtBScenario.add(comboAutoResolveType, gridBagConstraints);
+
+ chkAutoResolveVictoryChanceEnabled = new JCheckBox(
+ resources.getString("chkAutoResolveVictoryChanceEnabled.text"));
+ chkAutoResolveVictoryChanceEnabled.setToolTipText(
+ resources.getString("chkAutoResolveVictoryChanceEnabled.toolTipText"));
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = yTablePosition++;
+ panSubAtBScenario.add(chkAutoResolveVictoryChanceEnabled, gridBagConstraints);
chkUseDropShips = new JCheckBox(resources.getString("chkUseDropShips.text"));
chkUseDropShips.setToolTipText(resources.getString("chkUseDropShips.toolTipText"));
+ gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = yTablePosition++;
panSubAtBScenario.add(chkUseDropShips, gridBagConstraints);
@@ -8969,7 +8989,8 @@ public void setOptions(@Nullable CampaignOptions options,
chkRegionalMekVariations.setSelected(options.isRegionalMekVariations());
chkAttachedPlayerCamouflage.setSelected(options.isAttachedPlayerCamouflage());
chkPlayerControlsAttachedUnits.setSelected(options.isPlayerControlsAttachedUnits());
- chkUseBotControlledAutoResolve.setSelected(options.isPrincessBotAutoResolve());
+ comboAutoResolveType.setSelectedItem(options.getAutoResolveMethod());
+ chkAutoResolveVictoryChanceEnabled.setSelected(options.isAutoResolveVictoryChanceEnabled());
chkUseDropShips.setSelected(options.isUseDropShips());
chkUseWeatherConditions.setSelected(options.isUseWeatherConditions());
chkUseLightConditions.setSelected(options.isUseLightConditions());
@@ -9572,7 +9593,8 @@ public void updateOptions() {
options.setRegionalMekVariations(chkRegionalMekVariations.isSelected());
options.setAttachedPlayerCamouflage(chkAttachedPlayerCamouflage.isSelected());
options.setPlayerControlsAttachedUnits(chkPlayerControlsAttachedUnits.isSelected());
- options.setPrincessBotAutoResolve(chkUseBotControlledAutoResolve.isSelected());
+ options.setAutoResolveMethod(comboAutoResolveType.getSelectedItem());
+ options.setAutoResolveVictoryChanceEnabled(chkAutoResolveVictoryChanceEnabled.isSelected());
options.setUseWeatherConditions(chkUseWeatherConditions.isSelected());
options.setUseLightConditions(chkUseLightConditions.isSelected());
options.setUsePlanetaryConditions(chkUsePlanetaryConditions.isSelected());