diff --git a/MekHQ/data/universe/atbconfig.xml b/MekHQ/data/universe/atbconfig.xml
index 4d34d06134d..fbeda1ad6b9 100644
--- a/MekHQ/data/universe/atbconfig.xml
+++ b/MekHQ/data/universe/atbconfig.xml
@@ -155,14 +155,18 @@ of 4. An entry of the form option has a weight of 1.
follow yyyy-MM-dd format. Planet names much match the
name in planets.xml exactly.-->
- Outreach
- Solaris
- Arc-Royal
- Fletcher
- Galatea
- Westerhand
- Northwind
- Herotitus
+ Outreach
+ Solaris
+ Arc-Royal
+ Fletcher
+ Galatea
+ Westerhand
+ Northwind
+ Herotitus
+ Antallos (Port Krin)
+ Astrokaszy
+ Noisiel
+ Le Blanc
diff --git a/MekHQ/resources/mekhq/resources/AtBConfigDefaults.properties b/MekHQ/resources/mekhq/resources/AtBConfigDefaults.properties
index d952b4cdc32..2299b46c2e7 100644
--- a/MekHQ/resources/mekhq/resources/AtBConfigDefaults.properties
+++ b/MekHQ/resources/mekhq/resources/AtBConfigDefaults.properties
@@ -10,7 +10,7 @@ botLance.CLAN=1:LLLLL,1:LLLLM,1:LLLMM|1:LLMMM,1:LMMMM,2:MMMMM,1:MMMMH,1:MMMHH|1:
botLance.CS=1:LLLLLL,2:LLLLLM,2:LLLLMM,1:LLLMMM|1:LLLMMM,1:LLMMMM,1:LMMMMM,1:MMMMMM,1:MMMMMH,1:MMMMHH|1:MMMHHH,1:MMHHHH,1:MHHHHH,1:HHHHHH,1:HHHHHA,1:HHHHAA|2:HHHAAA,1:HHAAAA,2:HAAAAA,1:AAAAAA
#The following are not required for AtB to function and are only used if atbconfig.xml is missing or broken
-hiringHalls=3031-01-01,3067-10-15,Outreach|2700-01-01,,Solaris|3057-01-01,,Arc-Royal|3058-01-01,3081-03-15,Fletcher|2650-01-01,,Galatea|3000-01-01,,Westerhand|3057-01-01,3081-03-15,Northwind|3020-01-01,,Herotitus
+hiringHalls=3031-01-01,3067-10-15,great,Outreach|2700-01-01,,minor,Solaris|3057-01-01,,standard,Arc-Royal|3058-01-01,3081-03-15,minor,Fletcher|2650-01-01,,great,Galatea|3000-01-01,,great,Westerhand|3057-01-01,3081-03-15,great,Northwind|3020-01-01,,minor,Herotitus|2694-01-01,,questionable,Antallos (Port Krin)|2912-01-01,,questionable,Astrokaszy|3052-01-01,,minor,Noisiel|2811-01-01,3045-01-01,minor,Le Blanc
shipSearchCost=100000
shipSearchLengthWeeks=4
diff --git a/MekHQ/src/mekhq/campaign/againstTheBot/AtBConfiguration.java b/MekHQ/src/mekhq/campaign/againstTheBot/AtBConfiguration.java
index 18b22ae7ff3..17325b6d0ab 100644
--- a/MekHQ/src/mekhq/campaign/againstTheBot/AtBConfiguration.java
+++ b/MekHQ/src/mekhq/campaign/againstTheBot/AtBConfiguration.java
@@ -24,6 +24,9 @@
import megamek.common.*;
import megamek.common.annotations.Nullable;
import mekhq.MekHQ;
+import mekhq.campaign.universe.HiringHall;
+import mekhq.campaign.universe.Planet;
+import mekhq.campaign.universe.enums.HiringHallLevel;
import mekhq.utilities.MHQXMLUtility;
import mekhq.campaign.Campaign;
import mekhq.campaign.finances.Money;
@@ -72,7 +75,7 @@ public class AtBConfiguration {
private HashMap>> botLanceTables = new HashMap<>();
/* Contract generation */
- private ArrayList> hiringHalls;
+ private HashMap hiringHalls = new HashMap<>();
/* Personnel and unit markets */
private Money shipSearchCost;
@@ -87,7 +90,6 @@ public class AtBConfiguration {
MekHQ.getMHQOptions().getLocale());
private AtBConfiguration() {
- hiringHalls = new ArrayList<>();
dsTable = new WeightedTable<>();
jsTable = new WeightedTable<>();
shipSearchCost = Money.of(100000);
@@ -158,10 +160,16 @@ private void setAllValuesToDefaults() {
case "hiringHalls":
for (String entry : property.split("\\|")) {
String[] fields = entry.split(",");
- hiringHalls.add(new DatedRecord<>(
- !fields[0].isBlank() ? MHQXMLUtility.parseDate(fields[0]) : null,
- !fields[1].isBlank() ? MHQXMLUtility.parseDate(fields[1]) : null,
- fields[2]));
+ LocalDate startDate = !fields[0].isBlank() ? MHQXMLUtility.parseDate(fields[0]) : null;
+ LocalDate endDate = !fields[1].isBlank() ? MHQXMLUtility.parseDate(fields[1]) : null;
+ HiringHallLevel level = null;
+ try {
+ level = HiringHallLevel.valueOf(fields[2].toUpperCase());
+ } catch (IllegalArgumentException ex) {
+ level = HiringHallLevel.GREAT;
+ }
+ String name = fields[3];
+ hiringHalls.put(name, new HiringHall(level, startDate, endDate, name));
}
break;
case "shipSearchCost":
@@ -284,8 +292,16 @@ public static String getParentFactionType(final Faction faction) {
}
public boolean isHiringHall(String planet, LocalDate date) {
- return hiringHalls.stream().anyMatch( rec -> rec.getValue().equals(planet)
- && rec.fitsDate(date));
+ HiringHall hall = hiringHalls.get(planet);
+ return hall != null && hall.isActive(date);
+ }
+
+ public HiringHallLevel getHiringHallLevel(String planet, LocalDate date) {
+ HiringHall hall = hiringHalls.get(planet);
+ if (hall != null && hall.isActive(date)) {
+ return hall.getLevel();
+ }
+ return HiringHallLevel.NONE;
}
public Money getShipSearchCost() {
@@ -467,7 +483,20 @@ private void loadContractGenerationNodeFromXml(Node node) {
if (wn2.getAttributes().getNamedItem("end") != null) {
end = MHQXMLUtility.parseDate(wn2.getAttributes().getNamedItem("end").getTextContent());
}
- hiringHalls.add(new DatedRecord<>(start, end, wn2.getTextContent()));
+ HiringHallLevel level = HiringHallLevel.NONE;
+ if (wn2.getAttributes().getNamedItem("level") != null) {
+ try {
+ String text = wn2.getAttributes().getNamedItem("level").getTextContent().toUpperCase();
+ level = HiringHallLevel.valueOf(wn2.getAttributes().getNamedItem("level").getTextContent().toUpperCase());
+ } catch (IllegalArgumentException e) {
+ LogManager.getLogger().warn("Invalid value for Hiring Hall level, falling back to NONE: " + e);
+ }
+ } else {
+ // Backwards compatibility--hiring halls in atbconfig.xml should default to GREAT
+ level = HiringHallLevel.GREAT;
+ }
+ String planetName = wn2.getTextContent();
+ hiringHalls.put(planetName, new HiringHall(level, start, end, planetName));
}
}
}
diff --git a/MekHQ/src/mekhq/campaign/universe/HiringHall.java b/MekHQ/src/mekhq/campaign/universe/HiringHall.java
new file mode 100644
index 00000000000..85949f9c788
--- /dev/null
+++ b/MekHQ/src/mekhq/campaign/universe/HiringHall.java
@@ -0,0 +1,36 @@
+package mekhq.campaign.universe;
+
+import mekhq.campaign.universe.enums.HiringHallLevel;
+
+import java.time.LocalDate;
+
+public class HiringHall {
+ private HiringHallLevel level;
+ private LocalDate startDate;
+ private LocalDate endDate;
+ private String planetName;
+
+ public HiringHall(HiringHallLevel level, LocalDate startDate, LocalDate endDate, String planetName) {
+ this.level = level;
+ this.startDate = startDate;
+ this.endDate = endDate;
+ this.planetName = planetName;
+ }
+
+ public boolean isActive(LocalDate date) {
+ return ((startDate == null) || !startDate.isAfter(date))
+ && ((endDate == null) || !endDate.isBefore(date));
+ }
+
+ public String getPlanetName() {
+ return planetName;
+ }
+
+ public HiringHallLevel getLevel() {
+ return level;
+ }
+
+ public void setLevel(HiringHallLevel level) {
+ this.level = level;
+ }
+}
diff --git a/MekHQ/src/mekhq/campaign/universe/enums/HiringHallLevel.java b/MekHQ/src/mekhq/campaign/universe/enums/HiringHallLevel.java
new file mode 100644
index 00000000000..823121c2d5e
--- /dev/null
+++ b/MekHQ/src/mekhq/campaign/universe/enums/HiringHallLevel.java
@@ -0,0 +1,9 @@
+package mekhq.campaign.universe.enums;
+
+public enum HiringHallLevel {
+ NONE,
+ QUESTIONABLE,
+ MINOR,
+ STANDARD,
+ GREAT
+}