From 8955b03c6543de60d199ad885532c3aaf5681ec7 Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Sun, 6 Apr 2025 01:49:40 -0500
Subject: [PATCH 01/10] Refactored Phenotype Enum And Added Attribute
Randomization
- Replaced static resource-based getters in `Phenotype` with dynamic methods using resource bundles (`getLabel`, `getTooltip`, `getShortName`).
- Introduced attribute modifiers and bonus traits for `Phenotype`.
- Added the `isTrueborn` method for Clan phenotype classification.
- Deprecation of legacy methods like `getToolTipText`, `getName`, `parseFromString`, and `getGroupingName`.
- Reimplemented parsing logic with the `fromString` method supporting legacy inputs, labels, and ordinal formats.
- Implemented and applied random attribute generation in `RandomSkillPreferences` and `DefaultPersonnelGenerator`.
- Added UI elements and tooltips for randomizing attributes.
- Enhanced unit tests for attribute randomization and label validity.
---
.../CampaignOptionsDialog.properties | 10 +-
.../mekhq/resources/Personnel.properties | 21 -
.../mekhq/resources/Phenotype.properties | 25 ++
.../campaign/RandomSkillPreferences.java | 29 +-
.../personnel/enums/PersonnelRole.java | 69 +++-
.../campaign/personnel/enums/Phenotype.java | 363 +++++++++++------
.../generator/AbstractSkillGenerator.java | 15 +-
.../generator/DefaultPersonnelGenerator.java | 1 +
.../generator/DefaultSkillGenerator.java | 49 ++-
.../contents/AdvancementTab.java | 14 +-
MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java | 369 +++++++++++-------
.../personnel/enums/PhenotypeTest.java | 158 ++------
12 files changed, 691 insertions(+), 432 deletions(-)
create mode 100644 MekHQ/resources/mekhq/resources/Phenotype.properties
diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
index efaccbeb82f..60bdbe2b65f 100644
--- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
+++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
@@ -1790,12 +1790,20 @@ lblContractNegotiationXP.tooltip=How much experience does a contract negotiator
Recommended: Keep this disabled.
# skillRandomizationTab
lblSkillRandomizationTab.text=Skill Randomization Options \u270E
-lblExtraRandomness.text=Extra Randomness \u26A0
+lblExtraRandomness.text=Extra Random Skills \u26A0
lblExtraRandomness.tooltip=If checked, an additional 1d6 will be rolled per skill possessed by a\
\ newly created character. On a 1, the skill will be lowered, and on a 6 the skill will be raised.\
\
Warning: Due to the way experience levels are calculated, enabling this option will\
\ more frequently have characters created with slightly lower than normal experience levels.
+lblRandomizeAttributes.text=Extra Random Attributes \uD83C\uDF1F
+lblRandomizeAttributes.tooltip=If checked, an extra d6 is rolled for each of the character's ATOW Attributes.\
+ \
+ On a roll of a 6 the Attribute is increased by 1, and a second d6 is rolled. If that is also a 6, the Attribute is\
+ \ increased by 1 again; and so on, until 6s stop being rolled.\
+ \
+ On a roll of a 6 the Attribute is decreased by 1, and a second d6 is rolled. If that is also a 1, the Attribute is\
+ \ decreased by 1 again; and so on, until 1s stop being rolled.
lblPhenotypesPanel.text=Clan Trueborn Percentages
lblMekWarrior.text=MekWarrior
lblMekWarrior.tooltip=What percentage of Clan MekWarriors should have a Trueborn phenotype?
diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties
index 0549df466ad..becaffe85b5 100644
--- a/MekHQ/resources/mekhq/resources/Personnel.properties
+++ b/MekHQ/resources/mekhq/resources/Personnel.properties
@@ -306,27 +306,6 @@ PersonnelRole.ADMINISTRATOR_TRANSPORT.text=Admin/Transport
PersonnelRole.ADMINISTRATOR_HR.text=Admin/HR
PersonnelRole.DEPENDENT.text=Dependent
PersonnelRole.NONE.text=None
-# Phenotype Enum
-Phenotype.MEKWARRIOR.text=MekWarrior
-Phenotype.MEKWARRIOR.toolTipText=Probability of a trueborn person with appropriate bonuses for MekWarriors. Does not apply to non-clan factions.
-Phenotype.ELEMENTAL.text=Elemental
-Phenotype.ELEMENTAL.toolTipText=Probability of a trueborn person with appropriate bonuses for Elementals. Does not apply to non-clan factions.
-Phenotype.AEROSPACE.text=Aerospace
-Phenotype.AEROSPACE.groupingNameText=Aerospace Pilot
-Phenotype.AEROSPACE.toolTipText=Probability of a trueborn person with appropriate bonuses for Aerospace crews. Does not apply to non-clan factions.
-Phenotype.VEHICLE.text=Vehicle
-Phenotype.VEHICLE.groupingNameText=Vehicle Crew
-Phenotype.VEHICLE.toolTipText=Probability of a trueborn person with appropriate bonuses for Vehicle crews. This only applies to Clan Hell's Horses.
-Phenotype.PROTOMEK.text=ProtoMek
-Phenotype.PROTOMEK.groupingNameText=ProtoMek Pilot
-Phenotype.PROTOMEK.toolTipText=Probability of a trueborn person with appropriate bonuses for ProtoMek crews. Does not apply to non-clan factions, nor clans before 3060.
-Phenotype.NAVAL.text=Naval
-Phenotype.NAVAL.groupingNameText=Naval Commander
-Phenotype.NAVAL.toolTipText=Probability of a trueborn person with appropriate bonuses for Naval crews. This only applies to Clan Snow Raven and the Outworlds Alliance.
-Phenotype.NONE.text=None
-Phenotype.NONE.toolTipText=This person is freeborn
-Phenotype.GENERAL.text=General
-Phenotype.GENERAL.toolTipText=Error: this should never be displayed and is used for generation
# Profession Enum
Profession.MEKWARRIOR.text=MekWarrior
Profession.MEKWARRIOR.toolTipText=The MekWarrior Profession contains MekWarriors, LAM Pilots, and ProtoMek Pilots.
diff --git a/MekHQ/resources/mekhq/resources/Phenotype.properties b/MekHQ/resources/mekhq/resources/Phenotype.properties
new file mode 100644
index 00000000000..c81f60d4792
--- /dev/null
+++ b/MekHQ/resources/mekhq/resources/Phenotype.properties
@@ -0,0 +1,25 @@
+# suppress inspection "UnusedProperty" for whole file
+## General
+shortName.trueborn=Trueborn
+shortName.freeborn=Freeborn
+## Specific
+MEKWARRIOR.label=MekWarrior
+MEKWARRIOR.tooltip=Probability of a trueborn person with appropriate bonuses for MekWarriors. Does not apply to non-clan factions.
+ELEMENTAL.label=Elemental
+ELEMENTAL.tooltip=Probability of a trueborn person with appropriate bonuses for Elementals. Does not apply to non-clan factions.
+AEROSPACE.label=Aerospace
+AEROSPACE.groupingNameText=Aerospace Pilot
+AEROSPACE.tooltip=Probability of a trueborn person with appropriate bonuses for Aerospace crews. Does not apply to non-clan factions.
+VEHICLE.label=Vehicle
+VEHICLE.groupingNameText=Vehicle Crew
+VEHICLE.tooltip=Probability of a trueborn person with appropriate bonuses for Vehicle crews. This only applies to Clan Hell's Horses.
+PROTOMEK.label=ProtoMek
+PROTOMEK.groupingNameText=ProtoMek Pilot
+PROTOMEK.tooltip=Probability of a trueborn person with appropriate bonuses for ProtoMek crews. Does not apply to non-clan factions, nor clans before 3060.
+NAVAL.label=Naval
+NAVAL.groupingNameText=Naval Commander
+NAVAL.tooltip=Probability of a trueborn person with appropriate bonuses for Naval crews. This only applies to Clan Snow Raven and the Outworlds Alliance.
+NONE.label=None
+NONE.tooltip=This person is freeborn
+GENERAL.label=General
+GENERAL.tooltip=Error: this should never be displayed and is used for generation
diff --git a/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java b/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java
index 58f7c6a3b96..4103eaf8599 100644
--- a/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java
+++ b/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java
@@ -52,6 +52,7 @@ public class RandomSkillPreferences {
private int overallRecruitBonus;
Map recruitmentBonuses;
private boolean randomizeSkill;
+ private boolean randomizeAttributes;
private boolean useClanBonuses;
private int antiMekProb;
private int[] specialAbilityBonus;
@@ -68,7 +69,7 @@ public RandomSkillPreferences() {
overallRecruitBonus = 0;
recruitmentBonuses = new HashMap<>();
randomizeSkill = true;
- useClanBonuses = true;
+ randomizeAttributes = false;
antiMekProb = 10;
combatSmallArmsBonus = -3;
supportSmallArmsBonus = -10;
@@ -165,18 +166,34 @@ public void setSpecialAbilityBonus(int type, int bonus) {
}
}
+ public boolean randomizeSkill() {
+ return randomizeSkill;
+ }
+
public void setRandomizeSkill(boolean b) {
this.randomizeSkill = b;
}
- public boolean randomizeSkill() {
- return randomizeSkill;
+ public boolean isRandomizeAttributes() {
+ return randomizeAttributes;
+ }
+
+ public void setRandomizeAttributes(boolean isRandomizeAttributes) {
+ this.randomizeAttributes = isRandomizeAttributes;
}
+ /**
+ * @deprecated not in use.
+ */
+ @Deprecated(since = "0.50.05", forRemoval = true)
public void setUseClanBonuses(boolean b) {
this.useClanBonuses = b;
}
+ /**
+ * @deprecated not in use.
+ */
+ @Deprecated(since = "0.50.05", forRemoval = true)
public boolean useClanBonuses() {
return useClanBonuses;
}
@@ -269,7 +286,7 @@ public void writeToXML(final PrintWriter pw, int indent) {
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "commandSkillsModifier", commandSkillsModifier);
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "roleplaySkillsModifier", roleplaySkillsModifier);
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomizeSkill", randomizeSkill);
- MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useClanBonuses", useClanBonuses);
+ MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomizeAttributes", randomizeAttributes);
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "antiMekProb", antiMekProb);
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "combatSmallArmsBonus", combatSmallArmsBonus);
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "supportSmallArmsBonus", supportSmallArmsBonus);
@@ -303,8 +320,8 @@ public static RandomSkillPreferences generateRandomSkillPreferencesFromXml(Node
retVal.overallRecruitBonus = Integer.parseInt(wn2.getTextContent().trim());
} else if (wn2.getNodeName().equalsIgnoreCase("randomizeSkill")) {
retVal.randomizeSkill = wn2.getTextContent().equalsIgnoreCase("true");
- } else if (wn2.getNodeName().equalsIgnoreCase("useClanBonuses")) {
- retVal.useClanBonuses = wn2.getTextContent().equalsIgnoreCase("true");
+ } else if (wn2.getNodeName().equalsIgnoreCase("randomizeAttributes")) {
+ retVal.randomizeAttributes = wn2.getTextContent().equalsIgnoreCase("true");
} else if (wn2.getNodeName().equalsIgnoreCase("antiMekProb")) {
retVal.antiMekProb = Integer.parseInt(wn2.getTextContent().trim());
} else if (wn2.getNodeName().equalsIgnoreCase("combatSmallArmsBonus")) {
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
index 88f294b04e5..d2e80c9e348 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
@@ -37,6 +37,7 @@
import megamek.common.annotations.Nullable;
import megamek.logging.MMLogger;
import mekhq.MekHQ;
+import mekhq.campaign.personnel.skills.enums.SkillAttribute;
/**
* The PersonnelRole enum represents various roles a person can have. Each role is associated with a name, an optional
@@ -57,7 +58,16 @@ public enum PersonnelRole {
AEROSPACE_PILOT("PersonnelRole.AEROSPACE_PILOT.text", KeyEvent.VK_A),
CONVENTIONAL_AIRCRAFT_PILOT("PersonnelRole.CONVENTIONAL_AIRCRAFT_PILOT.text", KeyEvent.VK_C),
PROTOMEK_PILOT("PersonnelRole.PROTOMEK_PILOT.text", KeyEvent.VK_P),
- BATTLE_ARMOUR("PersonnelRole.BATTLE_ARMOUR.text", "PersonnelRole.BATTLE_ARMOUR.clan.text", KeyEvent.VK_B),
+ BATTLE_ARMOUR("PersonnelRole.BATTLE_ARMOUR.text",
+ "PersonnelRole.BATTLE_ARMOUR.clan.text",
+ KeyEvent.VK_B,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
SOLDIER("PersonnelRole.SOLDIER.text", KeyEvent.VK_S),
VESSEL_PILOT("PersonnelRole.VESSEL_PILOT.text", KeyEvent.VK_I),
VESSEL_GUNNER("PersonnelRole.VESSEL_GUNNER.text", KeyEvent.VK_U),
@@ -82,6 +92,13 @@ public enum PersonnelRole {
private final String name;
private final String clanName;
private final int mnemonic; // Unused: J, K, Q, X, Z
+ private final int strength;
+ private final int body;
+ private final int dexterity;
+ private final int reflexes;
+ private final int intelligence;
+ private final int willpower;
+ private final int charisma;
// endregion Variable Declarations
// region Constructors
@@ -93,7 +110,7 @@ public enum PersonnelRole {
* @param mnemonic the mnemonic of the personnel role
*/
PersonnelRole(final String name, final int mnemonic) {
- this(name, null, mnemonic);
+ this(name, null, mnemonic, 0, 0, 0, 0, 0, 0, 0);
}
/**
@@ -104,12 +121,21 @@ public enum PersonnelRole {
* @param clanName the clan name of the role can be {@code null}.
* @param mnemonic the mnemonic associated with the role.
*/
- PersonnelRole(final String name, @Nullable final String clanName, final int mnemonic) {
+ PersonnelRole(final String name, @Nullable final String clanName, final int mnemonic, final int strength,
+ final int body, final int reflexes, final int dexterity, final int intelligence, final int willpower,
+ final int charisma) {
final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel",
MekHQ.getMHQOptions().getLocale());
this.name = resources.getString(name);
this.clanName = (clanName == null) ? this.name : resources.getString(clanName);
this.mnemonic = mnemonic;
+ this.strength = strength;
+ this.body = body;
+ this.reflexes = reflexes;
+ this.dexterity = dexterity;
+ this.intelligence = intelligence;
+ this.willpower = willpower;
+ this.charisma = charisma;
}
// endregion Constructors
@@ -121,6 +147,43 @@ public String getName(final boolean isClan) {
public int getMnemonic() {
return mnemonic;
}
+
+ /**
+ * Retrieves the corresponding modifier value for the given {@link SkillAttribute}.
+ *
+ *
This method determines the modifier by matching the input {@link SkillAttribute}
+ * to its associated property within the class. The mapping is as follows:
+ *
+ *
{@link SkillAttribute#NONE}: Returns {@code 0} as no modification is applicable.
+ *
{@link SkillAttribute#STRENGTH}: Returns the value of the {@code strength} modifier.
+ *
{@link SkillAttribute#BODY}: Returns the value of the {@code body} modifier.
+ *
{@link SkillAttribute#REFLEXES}: Returns the value of the {@code reflexes} modifier.
+ *
{@link SkillAttribute#DEXTERITY}: Returns the value of the {@code dexterity} modifier.
+ *
{@link SkillAttribute#INTELLIGENCE}: Returns the value of the {@code intelligence} modifier.
+ *
{@link SkillAttribute#WILLPOWER}: Returns the value of the {@code willpower} modifier.
+ *
{@link SkillAttribute#CHARISMA}: Returns the value of the {@code charisma} modifier.
+ *
+ *
+ * @param attribute The {@link SkillAttribute} for which the modifier value is requested. Must not be {@code null}.
+ *
+ * @return The integer value of the modifier corresponding to the given {@link SkillAttribute}.
+ */
+ public int getAttributeModifier(final SkillAttribute attribute) {
+ if (attribute == null) {
+ return 0;
+ }
+
+ return switch (attribute) {
+ case NONE -> 0;
+ case STRENGTH -> strength;
+ case BODY -> body;
+ case REFLEXES -> reflexes;
+ case DEXTERITY -> dexterity;
+ case INTELLIGENCE -> intelligence;
+ case WILLPOWER -> willpower;
+ case CHARISMA -> charisma;
+ };
+ }
// endregion Getters
// region Boolean Comparison Methods
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java b/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java
index aee5955fe34..9439f19b693 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java
@@ -27,126 +27,111 @@
*/
package mekhq.campaign.personnel.enums;
-import megamek.logging.MMLogger;
-import mekhq.MekHQ;
+import static mekhq.utilities.MHQInternationalization.getFormattedTextAt;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
-import java.util.ResourceBundle;
-import java.util.stream.Collectors;
+
+import megamek.codeUtilities.MathUtility;
+import megamek.logging.MMLogger;
+import mekhq.campaign.personnel.skills.enums.SkillAttribute;
/**
- * The {@link Phenotype} Enum represents various phenotypes a Clan character can have.
- * Each {@link Phenotype} is associated with a name, short name, grouping name and a tooltip text.
- * Each {@link Phenotype} can be classified as either {@code external} or {@code internal}.
+ * The {@link Phenotype} Enum represents various phenotypes a Clan character can have. Each {@link Phenotype} is
+ * associated with a name, short name, grouping name and a tooltip text. Each {@link Phenotype} can be classified as
+ * either {@code external} or {@code internal}.
*/
public enum Phenotype {
// region Enum Declarations
/**
* Individual external phenotypes.
*/
- MEKWARRIOR("Phenotype.MEKWARRIOR.text", "Trueborn.text",
- "Phenotype.MEKWARRIOR.text", "Phenotype.MEKWARRIOR.toolTipText"),
- ELEMENTAL("Phenotype.ELEMENTAL.text", "Trueborn.text",
- "Phenotype.ELEMENTAL.text", "Phenotype.ELEMENTAL.toolTipText"),
- AEROSPACE("Phenotype.AEROSPACE.text", "Trueborn.text",
- "Phenotype.AEROSPACE.groupingNameText", "Phenotype.AEROSPACE.toolTipText"),
- VEHICLE("Phenotype.VEHICLE.text", "Trueborn.text",
- "Phenotype.VEHICLE.groupingNameText", "Phenotype.VEHICLE.toolTipText"),
- PROTOMEK("Phenotype.PROTOMEK.text", "Trueborn.text",
- "Phenotype.PROTOMEK.groupingNameText", "Phenotype.PROTOMEK.toolTipText"),
- NAVAL("Phenotype.NAVAL.text", "Trueborn.text",
- "Phenotype.NAVAL.groupingNameText", "Phenotype.NAVAL.toolTipText"),
+ MEKWARRIOR(true, true, 0, 0, 1, 1, new ArrayList<>()),
+ ELEMENTAL(true, true, 2, 1, -1, 0, List.of("atow_toughness")),
+ AEROSPACE(true, true, -1, -1, +2, +2, List.of("flaw_glass_jaw")),
+ // ATOW doesn't cover a vehicle phenotype, but as the linked attributes for vehicle skills are also reflexes and
+ // dexterity I copied the MekWarrior phenotype
+ VEHICLE(true, true, 0, 0, 1, 1, new ArrayList<>()),
+ // According to my research, ProtoMek pilots are normally just Aerospace washouts, so I'm assuming they'd have the
+ // same phenotype modifiers.
+ PROTOMEK(true, true, -1, -1, +2, +2, List.of("flaw_glass_jaw")),
+ // Copying the MekWarrior phenotype, same reasons as above.
+ NAVAL(true, true, 0, 0, 1, 1, new ArrayList<>()),
/**
* Individual internal phenotypes.
*/
// Internal Phenotypes
- NONE("Phenotype.NONE.text", "Freeborn.text",
- "Phenotype.NONE.text", "Phenotype.NONE.toolTipText", false),
- GENERAL("Phenotype.GENERAL.text", "Trueborn.text",
- "Phenotype.GENERAL.text", "Phenotype.GENERAL.toolTipText", false);
+ NONE(false, false, 0, 0, 0, 0, new ArrayList<>()),
+ GENERAL(false, false, 0, 0, 0, 0, new ArrayList<>());
// endregion Enum Declarations
// region Variable Declarations
- private final String name;
- private final String shortName;
- private final String groupingName;
- private final String toolTipText;
+ private static final MMLogger logger = MMLogger.create(Phenotype.class);
+ private static final String RESOURCE_BUNDLE = "mekhq.resources." + Phenotype.class.getSimpleName();
+
+ private final boolean isTrueborn;
private final boolean external;
+ private final int strength;
+ private final int body;
+ private final int reflexes;
+ private final int dexterity;
+ private final List bonusTraits;
// endregion Variable Declarations
// region Constructors
- /**
- * Overloaded constructor to create an external {@link Phenotype}.
- *
- * @param name the name of the phenotype.
- * @param shortName the short name for phenotype.
- * @param groupingName the group the phenotype belongs to.
- * @param toolTipText tooltip text for the phenotype.
- */
- Phenotype(final String name, final String shortName, final String groupingName,
- final String toolTipText) {
- this(name, shortName, groupingName, toolTipText, true);
+ Phenotype() {
+ this(false, false, 0, 0, 0, 0, new ArrayList<>());
}
- /**
- * Overloaded constructor to create a {@link Phenotype}, either external or internal.
- *
- * @param name the name of the phenotype.
- * @param shortName the short name for phenotype.
- * @param groupingName the group the phenotype belongs to.
- * @param toolTipText tooltip text for the phenotype.
- * @param external a boolean denoting whether the phenotype is internal ({@code false}) or
- * external ({@code true}).
- */
- Phenotype(final String name, final String shortName, final String groupingName,
- final String toolTipText, final boolean external) {
- final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel",
- MekHQ.getMHQOptions().getLocale());
- this.name = resources.getString(name);
- this.shortName = resources.getString(shortName);
- this.groupingName = resources.getString(groupingName);
- this.toolTipText = resources.getString(toolTipText);
+ Phenotype(final boolean isTrueborn, final boolean external, final int strength, final int body, final int reflexes,
+ final int dexterity, final List bonusTraits) {
+ this.isTrueborn = isTrueborn;
this.external = external;
+ this.strength = strength;
+ this.body = body;
+ this.reflexes = reflexes;
+ this.dexterity = dexterity;
+ this.bonusTraits = bonusTraits;
}
// endregion Constructors
// region Getters
+
/**
- * Retrieves the name of the phenotype.
- *
- * @return a {@link String} representing the name of the phenotype.
+ * @deprecated use {@link #getLabel()} instead
*/
+ @Deprecated(since = "0.50.05", forRemoval = true)
public String getName() {
- return name;
+ return getLabel();
}
/**
- * Retrieves the short name of the phenotype.
- *
- * @return a {@link String} representing the short name of the phenotype.
+ * @deprecated use {@link #getLabel()} instead
*/
- public String getShortName() {
- return shortName;
+ @Deprecated(since = "0.50.05", forRemoval = true)
+ public String getGroupingName() {
+ return getLabel();
}
/**
- * Retrieves the grouping name of the phenotype.
- *
- * @return a {@link String} representing the grouping name of the phenotype.
+ * @deprecated use {@link #getTooltip()} instead
*/
- public String getGroupingName() {
- return groupingName;
+ @Deprecated(since = "0.50.05", forRemoval = true)
+ public String getToolTipText() {
+ return getTooltip();
}
/**
- * Retrieves the tooltip text associated with the phenotype.
+ * Checks whether the phenotype is a Clan Trueborn phenotype.
*
- * @return a {@link String} representing the tooltip text of the phenotype.
+ * @return a boolean, {@code true} if the phenotype is Trueborn, otherwise {@code false}.
+ *
+ * @author Illiani
+ * @since 0.50.05
*/
- public String getToolTipText() {
- return toolTipText;
+ public boolean isTrueborn() {
+ return external;
}
/**
@@ -157,9 +142,101 @@ public String getToolTipText() {
public boolean isExternal() {
return external;
}
+
+ /**
+ * Retrieves the modifier value for a given skill attribute.
+ *
+ *
The method determines the corresponding modifier based on the
+ * specified {@link SkillAttribute}. The value is fetched from the associated field depending on the attribute:
+ *
+ *
For {@code STRENGTH}, the {@code strength} field is returned.
+ *
For {@code BODY}, the {@code body} field is returned.
+ *
For {@code REFLEXES}, the {@code reflexes} field is returned.
+ *
For {@code DEXTERITY}, the {@code dexterity} field is returned.
+ *
For {@code NONE}, {@code INTELLIGENCE}, {@code WILLPOWER}, and
+ * {@code CHARISMA}, a default value of {@code 0} is returned.
+ *
+ *
+ * @param attribute The skill attribute for which the modifier is requested.
+ *
+ * @return The modifier value associated with the provided attribute. If the attribute is {@code NONE},
+ * {@code INTELLIGENCE}, {@code WILLPOWER}, or {@code CHARISMA}, the method returns {@code 0}.
+ *
+ * @throws NullPointerException If the {@code attribute} is {@code null}.
+ */
+ public int getAttributeModifier(final SkillAttribute attribute) {
+ return switch (attribute) {
+ case STRENGTH -> strength;
+ case BODY -> body;
+ case REFLEXES -> reflexes;
+ case DEXTERITY -> dexterity;
+ case NONE, INTELLIGENCE, WILLPOWER, CHARISMA -> 0;
+ };
+ }
+
+ /**
+ * Retrieves a list of bonus traits assigned to this phenotype.
+ *
+ * @return A list of bonus traits as strings.
+ */
+ public List getBonusTraits() {
+ return bonusTraits;
+ }
+
+ /**
+ * Retrieves the short name of this phenotype based on its Clan status.
+ *
+ *
The method determines the appropriate key by appending the Clan status
+ * ("trueborn" or "freeborn") to the base key "shortName.". This key is then used to fetch the formatted text from
+ * the resource bundle.
+ *
+ * @return A formatted short name string corresponding to the born type (e.g., "shortName.trueborn" or
+ * "shortName.freeborn") from the resource bundle.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public String getShortName() {
+ String key = "shortName." + (isTrueborn ? "trueborn" : "freeborn");
+
+ return getFormattedTextAt(RESOURCE_BUNDLE, key);
+ }
+
+ /**
+ * Retrieves the label for this phenotype.
+ *
+ *
The method constructs the key by appending ".label" to the name of
+ * the current instance (as returned by {@code name()}) and uses it to fetch the formatted text from the resource
+ * bundle.
+ *
+ * @return A formatted label string corresponding to the key ".label" from the resource bundle.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public String getLabel() {
+ return getFormattedTextAt(RESOURCE_BUNDLE, name() + ".label");
+ }
+
+ /**
+ * Retrieves the tooltip text for this phenotype.
+ *
+ *
The method constructs the key by appending ".tooltip" to the name of
+ * the current instance (as returned by {@code name()}) and uses it to fetch the formatted text from the resource
+ * bundle.
+ *
+ * @return A formatted tooltip string corresponding to the key ".tooltip" from the resource bundle.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public String getTooltip() {
+ return getFormattedTextAt(RESOURCE_BUNDLE, name() + ".tooltip");
+ }
// endregion Getters
// region Boolean Comparison Methods
+
/**
* Checks if the phenotype is MekWarrior.
*
@@ -236,70 +313,122 @@ public boolean isGeneral() {
/**
* Retrieves a list of external phenotypes.
*
- * @return a {@link List} of {@link Phenotype} objects where {@code isExternal()} returns
- * {@code true}.
+ * @return a {@link List} of {@link Phenotype} objects where {@code isExternal()} returns {@code true}.
*/
public static List getExternalPhenotypes() {
- return Arrays.stream(values())
- .filter(Phenotype::isExternal)
- .collect(Collectors.toList());
+ List externalPhenotypes = new ArrayList<>();
+
+ for (Phenotype phenotype : values()) {
+ if (phenotype.isExternal()) {
+ externalPhenotypes.add(phenotype);
+ }
+ }
+
+ return externalPhenotypes;
}
+ // region File I/O
+
/**
- * Parses a string representation of a {@link Phenotype} and returns the corresponding phenotype
- * object.
- * If the string cannot be parsed into a valid phenotype, returns {@code Phenotype.NONE}.
- *
- * @param phenotype the string representation of the phenotype to parse
- * @return the parsed phenotype
+ * @deprecated use {@link #fromString(String)} instead.
*/
- // region File I/O
+ @Deprecated(since = "0.50.05", forRemoval = true)
public static Phenotype parseFromString(final String phenotype) {
+ return fromString(phenotype);
+ }
+
+ /**
+ * Converts a string representation to a corresponding {@link Phenotype} value.
+ *
+ *
This method attempts to parse the input string and return the appropriate
+ * {@link Phenotype} instance using the following approaches:
+ *
+ *
By name: Converts the input to uppercase, replaces spaces with underscores,
+ * and tries to match it using {@link Phenotype#valueOf(String)}.
+ *
By label (short name): Matches the input case-insensitively against
+ * the short name of each {@link Phenotype}.
+ *
Legacy compatibility: Matches certain input strings such as
+ * {@code "MECHWARRIOR"} and {@code "PROTOMECH"} to their updated {@link Phenotype} equivalents.
+ *
By ordinal: Parses the input as an integer and retrieves the
+ * phenotype corresponding to the specified ordinal.
+ *
+ *
+ *
If the input is {@code null} or none of the parsing approaches are successful,
+ * an error is logged, and the method defaults to returning {@link Phenotype#NONE}.
+ *
+ * @param text The string representation to parse. Supported input formats include:
+ *
+ *
The full name of the phenotype (case-insensitive, spaces allowed).
+ *
The short name (label) of the phenotype (case-insensitive).
+ *
Legacy names such as {@code "MECHWARRIOR"} or {@code "PROTOMECH"}.
+ *
An ordinal value corresponding to the phenotype.
+ *
+ *
+ * @return The corresponding {@link Phenotype} instance for the given input, or {@link Phenotype#NONE} if the input
+ * he input is invalid or {@code null}.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public static Phenotype fromString(String text) {
+ if (text == null || text.isBlank()) {
+ logger.error("Unable to parse text into a Phenotype. Returning NONE");
+ return NONE;
+ }
+
+ // Parse from name
try {
- return valueOf(phenotype);
- } catch (Exception ignored) {}
+ return Phenotype.valueOf(text.toUpperCase().replace(" ", "_"));
+ } catch (Exception ignored) {
+ }
+ // Parse from label
try {
- switch (Integer.parseInt(phenotype)) {
- case 0:
- return NONE;
- case 1:
- return MEKWARRIOR;
- case 2:
- return ELEMENTAL;
- case 3:
- return AEROSPACE;
- case 4:
- return VEHICLE;
- default:
- break;
+ for (Phenotype phenotype : Phenotype.values()) {
+ if (phenotype.getLabel().equalsIgnoreCase(text)) {
+ return phenotype;
+ }
}
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ }
// <50.1 compatibility
- switch (phenotype) {
- case "MECHWARRIOR" -> {
- return MEKWARRIOR;
- }
- case "PROTOMECH" -> {
- return PROTOMEK;
- }
- default -> {}
+ if (text.equalsIgnoreCase("MECHWARRIOR")) {
+ return MEKWARRIOR;
+ } else if (text.equalsIgnoreCase("PROTOMECH")) {
+ return PROTOMEK;
+ }
+
+ // Parse from ordinal
+ try {
+ return Phenotype.values()[MathUtility.parseInt(text, NONE.ordinal())];
+ } catch (Exception ignored) {
}
- MMLogger.create(Phenotype.class).error(
- String.format("Unable to parse %s into a Phenotype. Returning NONE.", phenotype));
+ logger.error("Unable to parse {} into a Phenotype. Returning NONE", text);
return NONE;
}
// endregion File I/O
/**
- * @return The string representation of a {@link Phenotype}.
- * If the phenotype is {@code None} or {@code General}, it returns short name.
- * Otherwise, it returns the short name followed by a space and group name.
+ * Returns a string representation of this phenotype.
+ *
+ *
The string is composed of the short name and, if the component is
+ * {@code trueborn}, the label is appended with a space separator. If the component is not {@code trueborn}, only
+ * the short name is included.
+ *
+ *
+ * @return A string representation consisting of the short name and, if applicable, the label, formatted as:
+ *
+ *
{@code "
+ *
{@code ""} if {@code trueborn} is {@code false}
+ *
+ *
+ * @author Illiani
+ * @since 0.50.05
*/
@Override
public String toString() {
- return (isNone() || isGeneral()) ? getShortName() : getShortName() + ' ' + getGroupingName();
+ return getShortName() + (isTrueborn ? ' ' + getLabel() : "");
}
}
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractSkillGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractSkillGenerator.java
index 36e822de292..795623e588c 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractSkillGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractSkillGenerator.java
@@ -35,8 +35,6 @@
import mekhq.campaign.Campaign;
import mekhq.campaign.RandomSkillPreferences;
import mekhq.campaign.personnel.Person;
-import mekhq.campaign.personnel.skills.Skill;
-import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.campaign.personnel.skills.Skill;
import mekhq.campaign.personnel.skills.SkillType;
@@ -78,6 +76,13 @@ public void setSkillPreferences(RandomSkillPreferences skillPreferences) {
*/
public abstract void generateSkills(Campaign campaign, Person person, int expLvl);
+ /**
+ * Generates attributes for a specified person based on their phenotype.
+ *
+ * @param person The {@link Person} for whom attributes are to be generated.
+ */
+ public abstract void generateAttributes(Person person);
+
/**
* Generates the default skills for a {@link Person} based on their primary role.
*
@@ -88,7 +93,7 @@ public void setSkillPreferences(RandomSkillPreferences skillPreferences) {
* @param rollModifier A roll modifier to apply to any randomizations.
*/
protected void generateDefaultSkills(Person person, PersonnelRole primaryRole, int expLvl, int bonus,
- int rollModifier) {
+ int rollModifier) {
switch (primaryRole) {
case MEKWARRIOR:
addSkill(person, SkillType.S_PILOT_MEK, expLvl, rskillPrefs.randomizeSkill(), bonus, rollModifier);
@@ -209,12 +214,12 @@ public static void addSkill(Person person, String skillName, int level, int bonu
}
protected static void addSkill(Person person, String skillName, int experienceLevel, boolean randomizeLevel,
- int bonus) {
+ int bonus) {
addSkill(person, skillName, experienceLevel, randomizeLevel, bonus, 0);
}
protected static void addSkill(Person person, String skillName, int experienceLevel, boolean randomizeLevel,
- int bonus, int rollMod) {
+ int bonus, int rollMod) {
if (randomizeLevel) {
person.addSkill(skillName, Skill.randomizeLevel(skillName, experienceLevel, bonus, rollMod));
} else {
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java
index 407a38ed3cb..8a2b9609d1d 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java
@@ -103,6 +103,7 @@ public Person generate(Campaign campaign, PersonnelRole primaryRole, PersonnelRo
AbstractSkillGenerator skillGenerator = new DefaultSkillGenerator(getSkillPreferences());
skillGenerator.generateSkills(campaign, person, expLvl);
+ skillGenerator.generateAttributes(person);
// Limit skills by age for children and adolescents
int age = person.getAge(campaign.getLocalDate());
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
index 04fdc07443e..d56464e4e55 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
@@ -27,6 +27,9 @@
*/
package mekhq.campaign.personnel.generator;
+import static megamek.common.Compute.d6;
+import static mekhq.campaign.personnel.skills.Attributes.MAXIMUM_ATTRIBUTE_SCORE;
+import static mekhq.campaign.personnel.skills.Attributes.MINIMUM_ATTRIBUTE_SCORE;
import static mekhq.campaign.personnel.skills.SkillDeprecationTool.DEPRECATED_SKILLS;
import static mekhq.campaign.personnel.skills.enums.SkillSubType.SUPPORT_COMMAND;
@@ -39,9 +42,10 @@
import mekhq.campaign.CampaignOptions;
import mekhq.campaign.RandomSkillPreferences;
import mekhq.campaign.personnel.Person;
-import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.personnel.enums.PersonnelRole;
+import mekhq.campaign.personnel.enums.Phenotype;
import mekhq.campaign.personnel.skills.SkillType;
+import mekhq.campaign.personnel.skills.enums.SkillAttribute;
public class DefaultSkillGenerator extends AbstractSkillGenerator {
//region Constructors
@@ -152,4 +156,47 @@ public void generateSkills(final Campaign campaign, final Person person, final i
addSkill(person, selSkill, secondLvl, rskillPrefs.randomizeSkill(), 0);
}
}
+
+ @Override
+ public void generateAttributes(Person person) {
+ RandomSkillPreferences skillPreferences = getSkillPreferences();
+ boolean extraRandomAttributes = skillPreferences.isRandomizeAttributes();
+
+ PersonnelRole profession = person.getPrimaryRole();
+ Phenotype phenotype = person.getPhenotype();
+ for (SkillAttribute attribute : SkillAttribute.values()) {
+ if (attribute.isNone()) {
+ continue;
+ }
+
+ // Profession && Phenotype adjustments
+ int attributeModifier = profession.getAttributeModifier(attribute);
+ attributeModifier += phenotype.getAttributeModifier(attribute);
+ person.changeAttributeScore(attribute, attributeModifier);
+
+ // Basic Attribute randomization
+ int roll = d6();
+
+ if (roll == 1) {
+ person.changeAttributeScore(attribute, -1);
+ } else if (roll == 6) {
+ person.changeAttributeScore(attribute, 1);
+ }
+
+ // Extra Attribute randomness
+ if (extraRandomAttributes) {
+ roll = d6();
+
+ if (roll == 1) {
+ do {
+ person.changeAttributeScore(attribute, -1);
+ } while ((d6() == 1) && (person.getAttributeScore(attribute) > MINIMUM_ATTRIBUTE_SCORE));
+ } else if (roll == 6) {
+ do {
+ person.changeAttributeScore(attribute, 1);
+ } while ((d6() == 1) && (person.getAttributeScore(attribute) < MAXIMUM_ATTRIBUTE_SCORE));
+ }
+ }
+ }
+ }
}
diff --git a/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java b/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java
index 53492cfed37..78e5869069e 100644
--- a/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java
+++ b/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java
@@ -43,7 +43,6 @@
import mekhq.campaign.Campaign;
import mekhq.campaign.CampaignOptions;
import mekhq.campaign.RandomSkillPreferences;
-import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.campaign.personnel.enums.Phenotype;
import mekhq.campaign.personnel.skills.SkillType;
@@ -114,6 +113,7 @@ public class AdvancementTab {
//start Skill Randomization Tab
private JCheckBox chkExtraRandomness;
+ private JCheckBox chkRandomizeAttributes;
private JPanel pnlPhenotype;
private JLabel[] phenotypeLabels;
@@ -520,6 +520,7 @@ private JPanel createAdministratorsPanel() {
*/
private void initializeSkillRandomizationTab() {
chkExtraRandomness = new JCheckBox();
+ chkRandomizeAttributes = new JCheckBox();
pnlPhenotype = new JPanel();
phenotypeLabels = new JLabel[] {}; // This will be initialized properly later
@@ -604,6 +605,7 @@ public JPanel skillRandomizationTab() {
// Contents
chkExtraRandomness = new CampaignOptionsCheckBox("ExtraRandomness");
+ chkRandomizeAttributes = new CampaignOptionsCheckBox("RandomizeAttributes");
pnlPhenotype = createPhenotypePanel();
pnlRandomAbilities = createAbilityPanel();
@@ -621,6 +623,10 @@ public JPanel skillRandomizationTab() {
layout.gridwidth = 1;
panel.add(chkExtraRandomness, layout);
+ layout.gridy++;
+ layout.gridwidth = 1;
+ panel.add(chkRandomizeAttributes, layout);
+
layout.gridx = 0;
layout.gridy++;
panel.add(pnlPhenotype, layout);
@@ -1100,7 +1106,7 @@ public void loadValuesFromCampaignOptions() {
* {@code null}, values are loaded from the current skill preferences.
*/
public void loadValuesFromCampaignOptions(@Nullable CampaignOptions presetCampaignOptions,
- @Nullable RandomSkillPreferences presetRandomSkillPreferences) {
+ @Nullable RandomSkillPreferences presetRandomSkillPreferences) {
CampaignOptions options = presetCampaignOptions;
if (presetCampaignOptions == null) {
options = this.campaignOptions;
@@ -1132,6 +1138,7 @@ public void loadValuesFromCampaignOptions(@Nullable CampaignOptions presetCampai
//start Skill Randomization Tab
chkExtraRandomness.setSelected(skillPreferences.randomizeSkill());
+ chkRandomizeAttributes.setSelected(skillPreferences.isRandomizeAttributes());
final int[] phenotypeProbabilities = options.getPhenotypeProbabilities();
for (int i = 0; i < phenotypeSpinners.length; i++) {
phenotypeSpinners[i].setValue(phenotypeProbabilities[i]);
@@ -1184,7 +1191,7 @@ public void loadValuesFromCampaignOptions(@Nullable CampaignOptions presetCampai
* {@code null}, values are applied to the current skill preferences.
*/
public void applyCampaignOptionsToCampaign(@Nullable CampaignOptions presetCampaignOptions,
- @Nullable RandomSkillPreferences presetRandomSkillPreferences) {
+ @Nullable RandomSkillPreferences presetRandomSkillPreferences) {
CampaignOptions options = presetCampaignOptions;
if (presetCampaignOptions == null) {
options = this.campaignOptions;
@@ -1216,6 +1223,7 @@ public void applyCampaignOptionsToCampaign(@Nullable CampaignOptions presetCampa
//start Skill Randomization Tab
skillPreferences.setRandomizeSkill(chkExtraRandomness.isSelected());
+ skillPreferences.setRandomizeAttributes(chkRandomizeAttributes.isSelected());
for (int i = 0; i < phenotypeSpinners.length; i++) {
options.setPhenotypeProbability(i, (int) phenotypeSpinners[i].getValue());
}
diff --git a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java
index b50257bc007..9633e122b32 100644
--- a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java
@@ -27,14 +27,42 @@
*/
package mekhq.gui.dialog;
+import static mekhq.campaign.personnel.backgrounds.BackgroundsController.randomMercenaryCompanyNameGenerator;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringJoiner;
+import java.util.function.Predicate;
+import javax.swing.*;
+import javax.swing.GroupLayout.Alignment;
+
import megamek.client.generator.RandomCallsignGenerator;
import megamek.client.generator.RandomNameGenerator;
import megamek.client.ui.baseComponents.MMButton;
import megamek.client.ui.baseComponents.MMComboBox;
import megamek.client.ui.dialogs.EntityReadoutDialog;
-import megamek.client.ui.preferences.*;
+import megamek.client.ui.preferences.JComboBoxPreference;
+import megamek.client.ui.preferences.JIntNumberSpinnerPreference;
+import megamek.client.ui.preferences.JTabbedPanePreference;
+import megamek.client.ui.preferences.JTextFieldPreference;
+import megamek.client.ui.preferences.PreferencesNode;
import megamek.codeUtilities.StringUtility;
-import megamek.common.*;
+import megamek.common.Compute;
+import megamek.common.Entity;
+import megamek.common.EntityWeightClass;
+import megamek.common.MekFileParser;
+import megamek.common.MekSummary;
+import megamek.common.Messages;
+import megamek.common.UnitType;
import megamek.common.annotations.Nullable;
import megamek.common.enums.Gender;
import megamek.logging.MMLogger;
@@ -58,19 +86,6 @@
import mekhq.gui.panels.LayeredForceIconCreationPanel;
import mekhq.gui.utilities.JScrollPaneWithSpeed;
-import javax.swing.*;
-import javax.swing.GroupLayout.Alignment;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.List;
-import java.util.Objects;
-import java.util.StringJoiner;
-import java.util.function.Predicate;
-
-import static mekhq.campaign.personnel.backgrounds.BackgroundsController.randomMercenaryCompanyNameGenerator;
-
public class GMToolsDialog extends AbstractMHQDialogBasic {
private static final MMLogger logger = MMLogger.create(GMToolsDialog.class);
@@ -151,7 +166,7 @@ public class GMToolsDialog extends AbstractMHQDialogBasic {
private static final String[] QUALITY_NAMES = { "F", "D", "C", "B", "A", "A*" };
private static final String[] WEIGHT_NAMES = { "Light", "Medium", "Heavy", "Assault" };
private static final Integer[] BLOODNAME_ERAS = { 2807, 2825, 2850, 2900, 2950, 3000, 3050, 3060, 3075, 3085,
- 3100 };
+ 3100 };
// endregion Constants
// endregion Variable Declarations
@@ -556,15 +571,11 @@ private JScrollPane createGeneralTab() {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(dicePanel)
- .addComponent(ratPanel));
+ layout.setVerticalGroup(layout.createSequentialGroup().addComponent(dicePanel).addComponent(ratPanel));
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(dicePanel)
- .addComponent(ratPanel));
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(dicePanel)
+ .addComponent(ratPanel));
return new JScrollPaneWithSpeed(panel);
}
@@ -623,8 +634,11 @@ private JPanel createDicePanel() {
gbc.gridx++;
panel.add(getLblTotalDiceResult(), gbc);
- final JButton btnDiceRoll = new MMButton("btnDiceRoll", resources, "btnDiceRoll.text",
- "btnDiceRoll.toolTipText", evt -> performDiceRoll());
+ final JButton btnDiceRoll = new MMButton("btnDiceRoll",
+ resources,
+ "btnDiceRoll.text",
+ "btnDiceRoll.toolTipText",
+ evt -> performDiceRoll());
gbc.gridx = maxGridX;
panel.add(btnDiceRoll, gbc);
@@ -701,7 +715,7 @@ private JPanel createRATPanel() {
final DefaultComboBoxModel factionModel = new DefaultComboBoxModel<>();
factionModel.addAll(FactionDisplay.getSortedValidFactionDisplays(Factions.getInstance().getFactions(),
- (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getDateOfBirth()));
+ (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getDateOfBirth()));
setComboRATFaction(new MMComboBox<>("comboRATFaction", factionModel));
getComboRATFaction().setSelectedIndex(0);
gbc.gridx++;
@@ -720,8 +734,9 @@ private JPanel createRATPanel() {
setComboUnitType(new MMComboBox<>("comboUnitType", unitTypeModel));
getComboUnitType().addItemListener(ev -> {
final int unitType = getComboUnitType().getSelectedIndex();
- getComboUnitWeight().setEnabled((unitType == UnitType.MEK) || (unitType == UnitType.TANK)
- || (unitType == UnitType.AEROSPACEFIGHTER));
+ getComboUnitWeight().setEnabled((unitType == UnitType.MEK) ||
+ (unitType == UnitType.TANK) ||
+ (unitType == UnitType.AEROSPACEFIGHTER));
});
gbc.gridx++;
panel.add(getComboUnitType(), gbc);
@@ -746,15 +761,21 @@ public void mouseClicked(final MouseEvent evt) {
gbc.gridwidth = maxGridX - (getGUI().getCampaign().isGM() ? 2 : 1);
panel.add(getLblUnitPicked(), gbc);
- final JButton btnRollRAT = new MMButton("btnRollRAT", resources, "btnRollRAT.text",
- "btnRollRAT.toolTipText", evt -> setLastRolledUnit(performRATRoll()));
+ final JButton btnRollRAT = new MMButton("btnRollRAT",
+ resources,
+ "btnRollRAT.text",
+ "btnRollRAT.toolTipText",
+ evt -> setLastRolledUnit(performRATRoll()));
gbc.gridx = getGUI().getCampaign().isGM() ? maxGridX - 1 : maxGridX;
gbc.gridwidth = 1;
panel.add(btnRollRAT, gbc);
if (getGUI().getCampaign().isGM()) {
- final JButton btnAddUnit = new MMButton("btnAddUnit", resources, "btnAddUnit.text",
- "btnAddUnit.toolTipText", evt -> addRATRolledUnit());
+ final JButton btnAddUnit = new MMButton("btnAddUnit",
+ resources,
+ "btnAddUnit.text",
+ "btnAddUnit.toolTipText",
+ evt -> addRATRolledUnit());
gbc.gridx++;
panel.add(btnAddUnit, gbc);
}
@@ -782,19 +803,17 @@ private JScrollPane createNamesTab() {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(namePanel)
- .addComponent(callsignPanel)
- .addComponent(companyNamePanel)
- .addComponent(bloodnamePanel));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(namePanel)
+ .addComponent(callsignPanel)
+ .addComponent(companyNamePanel)
+ .addComponent(bloodnamePanel));
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(namePanel)
- .addComponent(callsignPanel)
- .addComponent(companyNamePanel)
- .addComponent(bloodnamePanel));
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(namePanel)
+ .addComponent(callsignPanel)
+ .addComponent(companyNamePanel)
+ .addComponent(bloodnamePanel));
return new JScrollPaneWithSpeed(namesPanel);
}
@@ -847,7 +866,7 @@ private JPanel createNamePanel() {
final DefaultComboBoxModel factionModel = new DefaultComboBoxModel<>();
factionModel.addAll(FactionDisplay.getSortedValidFactionDisplays(Factions.getInstance().getFactions(),
- (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getDateOfBirth()));
+ (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getDateOfBirth()));
setComboNameGeneratorFaction(new MMComboBox<>("comboRATFaction", factionModel));
getComboNameGeneratorFaction().setSelectedIndex(0);
gbc.gridx++;
@@ -860,8 +879,8 @@ private JPanel createNamePanel() {
}
setComboEthnicCode(new MMComboBox<>("comboEthnicCode", historicalEthnicityModel));
getComboEthnicCode().setSelectedIndex(0);
- getComboEthnicCode().addActionListener(
- evt -> getComboNameGeneratorFaction().setEnabled(getComboEthnicCode().getSelectedIndex() == 0));
+ getComboEthnicCode().addActionListener(evt -> getComboNameGeneratorFaction().setEnabled(getComboEthnicCode().getSelectedIndex() ==
+ 0));
gbc.gridx++;
panel.add(getComboEthnicCode(), gbc);
@@ -889,9 +908,9 @@ private JPanel createNamePanel() {
gbc.gridx++;
}
- final JLabel lblNameGenerated = new JLabel(resources.getString((getPerson() == null)
- ? "lblNamesGenerated.text"
- : "lblNameGenerated.text"));
+ final JLabel lblNameGenerated = new JLabel(resources.getString((getPerson() == null) ?
+ "lblNamesGenerated.text" :
+ "lblNameGenerated.text"));
lblNameGenerated.setName((getPerson() == null) ? "lblNamesGenerated" : "lblNameGenerated");
panel.add(lblNameGenerated, gbc);
@@ -906,19 +925,28 @@ private JPanel createNamePanel() {
gbc.gridx = maxGridX - 1;
panel.add(getSpnNameNumber(), gbc);
- final JButton btnGenerateNames = new MMButton("btnGenerateNames", resources,
- "btnGenerateNames.text", "btnGenerateNames.toolTipText", evt -> generateNames());
+ final JButton btnGenerateNames = new MMButton("btnGenerateNames",
+ resources,
+ "btnGenerateNames.text",
+ "btnGenerateNames.toolTipText",
+ evt -> generateNames());
gbc.gridx++;
panel.add(btnGenerateNames, gbc);
} else {
- final JButton btnAssignName = new MMButton("btnAssignName", resources,
- "btnAssignName.text", "btnAssignName.toolTipText", evt -> assignName());
+ final JButton btnAssignName = new MMButton("btnAssignName",
+ resources,
+ "btnAssignName.text",
+ "btnAssignName.toolTipText",
+ evt -> assignName());
gbc.gridx = maxGridX - 1;
gbc.gridy++;
panel.add(btnAssignName, gbc);
- final JButton btnGenerateName = new MMButton("btnGenerateName", resources,
- "btnGenerateName.text", "btnGenerateName.toolTipText", evt -> generateName());
+ final JButton btnGenerateName = new MMButton("btnGenerateName",
+ resources,
+ "btnGenerateName.text",
+ "btnGenerateName.toolTipText",
+ evt -> generateName());
gbc.gridx++;
panel.add(btnGenerateName, gbc);
}
@@ -965,9 +993,9 @@ private JPanel createCallsignPanel() {
gbc.gridx++;
}
- final JLabel lblCallsignGenerated = new JLabel(resources.getString((getPerson() == null)
- ? "lblCallsignsGenerated.text"
- : "lblCallsignGenerated.text"));
+ final JLabel lblCallsignGenerated = new JLabel(resources.getString((getPerson() == null) ?
+ "lblCallsignsGenerated.text" :
+ "lblCallsignGenerated.text"));
lblCallsignGenerated.setName((getPerson() == null) ? "lblCallsignsGenerated" : "lblCallsignGenerated");
panel.add(lblCallsignGenerated, gbc);
@@ -984,19 +1012,28 @@ private JPanel createCallsignPanel() {
gbc.gridx++;
panel.add(getSpnCallsignNumber(), gbc);
- final JButton btnGenerateCallsigns = new MMButton("btnGenerateCallsigns", resources,
- "btnGenerateCallsigns.text", "btnGenerateCallsigns.toolTipText", evt -> generateCallsigns());
+ final JButton btnGenerateCallsigns = new MMButton("btnGenerateCallsigns",
+ resources,
+ "btnGenerateCallsigns.text",
+ "btnGenerateCallsigns.toolTipText",
+ evt -> generateCallsigns());
gbc.gridx++;
panel.add(btnGenerateCallsigns, gbc);
} else {
- final JButton btnAssignCallsign = new MMButton("btnAssignCallsign", resources,
- "btnAssignCallsign.text", "btnAssignCallsign.toolTipText", evt -> assignCallsign());
+ final JButton btnAssignCallsign = new MMButton("btnAssignCallsign",
+ resources,
+ "btnAssignCallsign.text",
+ "btnAssignCallsign.toolTipText",
+ evt -> assignCallsign());
gbc.gridx = maxGridX - 1;
gbc.gridy++;
panel.add(btnAssignCallsign, gbc);
- final JButton btnGenerateCallsign = new MMButton("btnGenerateCallsign", resources,
- "btnGenerateCallsign.text", "btnGenerateCallsign.toolTipText", evt -> generateCallsign());
+ final JButton btnGenerateCallsign = new MMButton("btnGenerateCallsign",
+ resources,
+ "btnGenerateCallsign.text",
+ "btnGenerateCallsign.toolTipText",
+ evt -> generateCallsign());
gbc.gridx++;
panel.add(btnGenerateCallsign, gbc);
}
@@ -1014,8 +1051,7 @@ private void addComponent(JPanel panel, Component component, GridBagConstraints
}
/**
- * Creates and returns a JPanel containing components related to the generation
- * of random company names.
+ * Creates and returns a JPanel containing components related to the generation of random company names.
*/
private JPanel createCompanyName() {
// Create the Panel
@@ -1057,43 +1093,39 @@ private JPanel createCompanyName() {
}
/**
- * Creates a MMButton object that generates a company name and updates the
- * appropriate JTextArea with the generated name.
+ * Creates a MMButton object that generates a company name and updates the appropriate JTextArea with the generated
+ * name.
*
- * @return a MMButton object that generates a company name and updates the given
- * JTextArea
+ * @return a MMButton object that generates a company name and updates the given JTextArea
*/
private MMButton createGenerateNameButton() {
return new MMButton("btnGenerateCompanyName",
- resources,
- "btnGenerateCompanyName.text",
- "btnGenerateCompanyName.toolTipText",
- evt -> {
- lastGeneratedCompanyName = randomMercenaryCompanyNameGenerator(
- gui.getCampaign().getFlaggedCommander());
- txtCompanyNamesGenerated.setText(lastGeneratedCompanyName);
- });
+ resources,
+ "btnGenerateCompanyName.text",
+ "btnGenerateCompanyName.toolTipText",
+ evt -> {
+ lastGeneratedCompanyName = randomMercenaryCompanyNameGenerator(gui.getCampaign()
+ .getFlaggedCommander());
+ txtCompanyNamesGenerated.setText(lastGeneratedCompanyName);
+ });
}
/**
- * Creates an instance of MMButton with the label "btnAssignCompanyName" and
- * sets the resource bundle,
- * text key, tooltip text key, and event handler for the button.
+ * Creates an instance of MMButton with the label "btnAssignCompanyName" and sets the resource bundle, text key,
+ * tooltip text key, and event handler for the button.
*
* @return an instance of MMButton with the specified properties
*/
private MMButton createAssignCompanyNameButton() {
- return new MMButton(
- "btnAssignCompanyName",
- resources,
- "btnAssignCompanyName.text",
- "btnAssignCompanyName.toolTipText",
- this::assignCompanyName);
+ return new MMButton("btnAssignCompanyName",
+ resources,
+ "btnAssignCompanyName.text",
+ "btnAssignCompanyName.toolTipText",
+ this::assignCompanyName);
}
/**
- * Assigns the company name to the campaign and origin force based on certain
- * conditions.
+ * Assigns the company name to the campaign and origin force based on certain conditions.
*
* @param evt the ActionEvent associated with the button click
*/
@@ -1138,7 +1170,7 @@ private JPanel createBloodnamePanel() {
final DefaultComboBoxModel originClanModel = new DefaultComboBoxModel<>();
originClanModel.addAll(ClanDisplay.getSortedClanDisplays(Clan.getClans(),
- getGUI().getCampaign().getLocalDate()));
+ getGUI().getCampaign().getLocalDate()));
setComboOriginClan(new MMComboBox<>("comboOriginClan", originClanModel));
getComboOriginClan().setSelectedIndex(0);
getComboOriginClan().addActionListener(evt -> validateBloodnameInput());
@@ -1161,12 +1193,12 @@ private JPanel createBloodnamePanel() {
getComboPhenotype().setSelectedItem(Phenotype.GENERAL);
getComboPhenotype().setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(final JList> list, final Object value,
- final int index, final boolean isSelected,
- final boolean cellHasFocus) {
+ public Component getListCellRendererComponent(final JList> list, final Object value, final int index,
+ final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
- setText((value == null) ? ""
- : ((value instanceof Phenotype) ? ((Phenotype) value).getGroupingName() : "ERROR"));
+ setText((value == null) ?
+ "" :
+ ((value instanceof Phenotype) ? ((Phenotype) value).getLabel() : "ERROR"));
return this;
}
});
@@ -1231,15 +1263,21 @@ public Component getListCellRendererComponent(final JList> list, final Object
gbc.gridwidth = maxGridX - ((getPerson() == null) ? 1 : 2);
panel.add(getLblBloodnameWarning(), gbc);
- final JButton btnGenerateBloodname = new MMButton("btnGenerateBloodname", resources,
- "btnGenerateBloodname.text", "btnGenerateBloodname.toolTipText", evt -> generateBloodname());
+ final JButton btnGenerateBloodname = new MMButton("btnGenerateBloodname",
+ resources,
+ "btnGenerateBloodname.text",
+ "btnGenerateBloodname.toolTipText",
+ evt -> generateBloodname());
gbc.gridx = maxGridX - ((getPerson() == null) ? 0 : 1);
gbc.gridwidth = 1;
panel.add(btnGenerateBloodname, gbc);
if (getPerson() != null) {
- final JButton btnAssignBloodname = new MMButton("btnAssignBloodname", resources,
- "btnAssignBloodname.text", "btnAssignBloodname.toolTipText", evt -> assignBloodname());
+ final JButton btnAssignBloodname = new MMButton("btnAssignBloodname",
+ resources,
+ "btnAssignBloodname.text",
+ "btnAssignBloodname.toolTipText",
+ evt -> assignBloodname());
gbc.gridx++;
panel.add(btnAssignBloodname, gbc);
}
@@ -1262,21 +1300,17 @@ private JScrollPane createPersonnelModuleTab() {
final JPanel procreationPanel = createProcreationPanel();
// Layout the Panel
- final AbstractMHQScrollablePanel personnelModulePanel = new DefaultMHQScrollablePanel(
- getFrame(), "personnelModulePanel");
+ final AbstractMHQScrollablePanel personnelModulePanel = new DefaultMHQScrollablePanel(getFrame(),
+ "personnelModulePanel");
final GroupLayout layout = new GroupLayout(personnelModulePanel);
personnelModulePanel.setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(procreationPanel));
+ layout.setVerticalGroup(layout.createSequentialGroup().addComponent(procreationPanel));
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(procreationPanel));
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(procreationPanel));
return new JScrollPaneWithSpeed(personnelModulePanel);
}
@@ -1309,13 +1343,15 @@ private JPanel createProcreationPanel() {
panel.add(lblEligibility, gbc);
setChkProcreationEligibilityType(new JCheckBox(resources.getString("chkProcreationEligibilityType.text")));
- getChkProcreationEligibilityType()
- .setToolTipText(resources.getString("chkProcreationEligibilityType.toolTipText"));
+ getChkProcreationEligibilityType().setToolTipText(resources.getString(
+ "chkProcreationEligibilityType.toolTipText"));
getChkProcreationEligibilityType().setName("chkProcreationEligibilityType");
getChkProcreationEligibilityType().addActionListener(evt -> {
- final String reason = getGUI().getCampaign().getProcreation().canProcreate(
- getGUI().getCampaign().getLocalDate(), getPerson(),
- getChkProcreationEligibilityType().isSelected());
+ final String reason = getGUI().getCampaign()
+ .getProcreation()
+ .canProcreate(getGUI().getCampaign().getLocalDate(),
+ getPerson(),
+ getChkProcreationEligibilityType().isSelected());
lblEligibility.setText(resources.getString((reason == null) ? "True.text" : "False.text"));
lblEligibility.setToolTipText(reason);
});
@@ -1329,8 +1365,8 @@ private JPanel createProcreationPanel() {
}
final JPanel procreationSimulationPanel = new JPanel();
- procreationSimulationPanel
- .setBorder(BorderFactory.createTitledBorder(resources.getString("procreationSimulationPanel.title")));
+ procreationSimulationPanel.setBorder(BorderFactory.createTitledBorder(resources.getString(
+ "procreationSimulationPanel.title")));
procreationSimulationPanel.setToolTipText(resources.getString("procreationSimulationPanel.toolTipText"));
procreationSimulationPanel.setName("procreationSimulationPanel");
@@ -1413,9 +1449,9 @@ private void setValuesFromPerson() {
}
}
- final Clan clan = Clan.getClan((getGUI().getCampaign().getFaction().isClan()
- ? getGUI().getCampaign().getFaction()
- : getPerson().getOriginFaction()).getShortName());
+ final Clan clan = Clan.getClan((getGUI().getCampaign().getFaction().isClan() ?
+ getGUI().getCampaign().getFaction() :
+ getPerson().getOriginFaction()).getShortName());
if (clan != null) {
getComboOriginClan().setSelectedItem(new ClanDisplay(clan, getGUI().getCampaign().getLocalDate()));
}
@@ -1434,8 +1470,8 @@ private boolean doesPersonPrimarilyDriveUnitType(final int unitType) {
case UnitType.BATTLE_ARMOR:
return getPerson().getPrimaryRole().isBattleArmour();
case UnitType.CONV_FIGHTER:
- return getPerson().getPrimaryRole().isConventionalAircraftPilot()
- || getPerson().getPrimaryRole().isAerospacePilot();
+ return getPerson().getPrimaryRole().isConventionalAircraftPilot() ||
+ getPerson().getPrimaryRole().isAerospacePilot();
case UnitType.DROPSHIP:
case UnitType.JUMPSHIP:
case UnitType.SMALL_CRAFT:
@@ -1462,9 +1498,10 @@ private boolean doesPersonPrimarilyDriveUnitType(final int unitType) {
// region ActionEvent Handlers
public void performDiceRoll() {
final List individualDice = Compute.individualRolls((Integer) getSpnDiceCount().getValue(),
- (Integer) getSpnDiceNumber().getValue(), (Integer) getSpnDiceSides().getValue());
- getLblTotalDiceResult()
- .setText(String.format(resources.getString("lblTotalDiceResult.text"), individualDice.get(0)));
+ (Integer) getSpnDiceNumber().getValue(),
+ (Integer) getSpnDiceSides().getValue());
+ getLblTotalDiceResult().setText(String.format(resources.getString("lblTotalDiceResult.text"),
+ individualDice.get(0)));
final StringBuilder sb = new StringBuilder();
for (int i = 1; i < individualDice.size() - 1; i++) {
@@ -1484,17 +1521,32 @@ public void performDiceRoll() {
return null;
}
- final Predicate predicate = summary -> (!getGUI().getCampaign().getCampaignOptions().isLimitByYear()
- || (targetYear > summary.getYear()))
- && (!summary.isClan() || getGUI().getCampaign().getCampaignOptions().isAllowClanPurchases())
- && (summary.isClan() || getGUI().getCampaign().getCampaignOptions().isAllowISPurchases());
+ final Predicate predicate = summary -> (!getGUI().getCampaign()
+ .getCampaignOptions()
+ .isLimitByYear() ||
+ (targetYear > summary.getYear())) &&
+ (!summary.isClan() ||
+ getGUI().getCampaign()
+ .getCampaignOptions()
+ .isAllowClanPurchases()) &&
+ (summary.isClan() ||
+ getGUI().getCampaign()
+ .getCampaignOptions()
+ .isAllowISPurchases());
final int unitType = UnitType.determineUnitTypeCode(getComboUnitType().getSelectedItem());
- final int unitWeight = getComboUnitWeight().isEnabled()
- ? getComboUnitWeight().getSelectedIndex() + EntityWeightClass.WEIGHT_LIGHT
- : AtBDynamicScenarioFactory.UNIT_WEIGHT_UNSPECIFIED;
- final MekSummary summary = getGUI().getCampaign().getUnitGenerator()
- .generate(Objects.requireNonNull(getComboRATFaction().getSelectedItem()).getFaction().getShortName(),
- unitType, unitWeight, targetYear, getComboQuality().getSelectedIndex(), predicate);
+ final int unitWeight = getComboUnitWeight().isEnabled() ?
+ getComboUnitWeight().getSelectedIndex() + EntityWeightClass.WEIGHT_LIGHT :
+ AtBDynamicScenarioFactory.UNIT_WEIGHT_UNSPECIFIED;
+ final MekSummary summary = getGUI().getCampaign()
+ .getUnitGenerator()
+ .generate(Objects.requireNonNull(getComboRATFaction().getSelectedItem())
+ .getFaction()
+ .getShortName(),
+ unitType,
+ unitWeight,
+ targetYear,
+ getComboQuality().getSelectedIndex(),
+ predicate);
if (summary == null) {
getLblUnitPicked().setText(Messages.getString("noValidUnit.error"));
@@ -1507,7 +1559,8 @@ public void performDiceRoll() {
return entity;
} catch (Exception ex) {
final String message = String.format(Messages.getString("entityLoadFailure.error"),
- summary.getName(), summary.getSourceFile());
+ summary.getName(),
+ summary.getSourceFile());
logger.error(message, ex);
getLblUnitPicked().setText(message);
return null;
@@ -1558,13 +1611,16 @@ private String[] generateIndividualName() {
final String[] name;
if (ethnicCode == 0) {
- name = RandomNameGenerator.getInstance().generateGivenNameSurnameSplit(
- getComboGender().getSelectedItem(), getChkClanPersonnel().isSelected(),
- (Objects.requireNonNull(getComboNameGeneratorFaction().getSelectedItem()))
- .getFaction().getShortName());
+ name = RandomNameGenerator.getInstance()
+ .generateGivenNameSurnameSplit(getComboGender().getSelectedItem(),
+ getChkClanPersonnel().isSelected(),
+ (Objects.requireNonNull(getComboNameGeneratorFaction().getSelectedItem())).getFaction()
+ .getShortName());
} else {
- name = RandomNameGenerator.getInstance().generateGivenNameSurnameSplitWithEthnicCode(
- getComboGender().getSelectedItem(), getChkClanPersonnel().isSelected(), ethnicCode);
+ name = RandomNameGenerator.getInstance()
+ .generateGivenNameSurnameSplitWithEthnicCode(getComboGender().getSelectedItem(),
+ getChkClanPersonnel().isSelected(),
+ ethnicCode);
}
return name;
}
@@ -1610,11 +1666,12 @@ private void assignCallsign() {
private void generateBloodname() {
final Bloodname bloodname = Bloodname.randomBloodname(getOriginClan(),
- getSelectedPhenotype(), getBloodnameYear());
+ getSelectedPhenotype(),
+ getBloodnameYear());
if (bloodname != null) {
getLblBloodnameGenerated().setText(bloodname.getName() + " (" + bloodname.getFounder() + ')');
getLblOriginClanGenerated().setText(bloodname.getOriginClan().getFullName(getBloodnameYear()));
- getLblPhenotypeGenerated().setText(bloodname.getPhenotype().getGroupingName());
+ getLblPhenotypeGenerated().setText(bloodname.getPhenotype().getLabel());
setLastGeneratedBloodname(bloodname.getName());
}
}
@@ -1632,13 +1689,13 @@ private void assignBloodname() {
}
private void validateBloodnameInput() {
- setOriginClan((getComboOriginClan().getSelectedItem() == null) ? null
- : getComboOriginClan().getSelectedItem().getClan());
+ setOriginClan((getComboOriginClan().getSelectedItem() == null) ?
+ null :
+ getComboOriginClan().getSelectedItem().getClan());
setBloodnameYear(BLOODNAME_ERAS[getComboBloodnameEra().getSelectedIndex()]);
setSelectedPhenotype(getComboPhenotype().getSelectedItem());
- if ((getOriginClan() == null) || (getSelectedPhenotype() == null)
- || getSelectedPhenotype().isNone()) {
+ if ((getOriginClan() == null) || (getSelectedPhenotype() == null) || getSelectedPhenotype().isNone()) {
return;
}
@@ -1648,8 +1705,13 @@ private void validateBloodnameInput() {
for (int era : BLOODNAME_ERAS) {
if (era >= getOriginClan().getStartDate()) {
setBloodnameYear(era);
- txt += "
" + getOriginClan().getFullName(getBloodnameYear()) + " formed in "
- + getOriginClan().getStartDate() + ". Using " + getBloodnameYear() + ".
";
+ txt += "
" +
+ getOriginClan().getFullName(getBloodnameYear()) +
+ " formed in " +
+ getOriginClan().getStartDate() +
+ ". Using " +
+ getBloodnameYear() +
+ ".
";
break;
}
}
@@ -1661,8 +1723,13 @@ private void validateBloodnameInput() {
for (int i = BLOODNAME_ERAS.length - 1; i >= 0; i--) {
if (BLOODNAME_ERAS[i] <= getOriginClan().getEndDate()) {
setBloodnameYear(BLOODNAME_ERAS[i]);
- txt += "
" + getOriginClan().getFullName(getBloodnameYear()) + " ceased to existed in "
- + getOriginClan().getEndDate() + ". Using " + getBloodnameYear() + ".
";
+ txt += "
" +
+ getOriginClan().getFullName(getBloodnameYear()) +
+ " ceased to existed in " +
+ getOriginClan().getEndDate() +
+ ". Using " +
+ getBloodnameYear() +
+ ".
*
- * @return A formatted label string corresponding to the key ".label" from the resource bundle.
+ * @return A formatted label string corresponding to the key "{@code Component Name}.label" from the resource
+ * bundle.
*
* @author Illiani
* @since 0.50.05
@@ -225,7 +226,8 @@ public String getLabel() {
* the current instance (as returned by {@code name()}) and uses it to fetch the formatted text from the resource
* bundle.
*
- * @return A formatted tooltip string corresponding to the key ".tooltip" from the resource bundle.
+ * @return A formatted tooltip string corresponding to the key "{@code Component Name}.tooltip" from the resource
+ * bundle.
*
* @author Illiani
* @since 0.50.05
From 25cfc82208e5fcbb0deff28a3c9328bcb8f8012e Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Sun, 6 Apr 2025 02:07:51 -0500
Subject: [PATCH 03/10] Enhanced Special Ability Generation With Phenotype
Traits
- Added phenotype-based SPA generation by incorporating bonus traits from a character's phenotype.
- Imported `LVL3_ADVANTAGES` and adjusted logic to acquire phenotype traits as abilities.
- Refactored minor formatting issues for improved readability.
---
.../DefaultSpecialAbilityGenerator.java | 22 +++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSpecialAbilityGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSpecialAbilityGenerator.java
index 044cb12e7c0..b8978b07a1b 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSpecialAbilityGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSpecialAbilityGenerator.java
@@ -27,14 +27,18 @@
*/
package mekhq.campaign.personnel.generator;
+import static megamek.common.options.PilotOptions.LVL3_ADVANTAGES;
+
+import java.util.List;
+
import mekhq.Utilities;
import mekhq.campaign.Campaign;
import mekhq.campaign.personnel.Person;
+import mekhq.campaign.personnel.enums.Phenotype;
public class DefaultSpecialAbilityGenerator extends AbstractSpecialAbilityGenerator {
@Override
- public boolean generateSpecialAbilities(final Campaign campaign, final Person person,
- final int expLvl) {
+ public boolean generateSpecialAbilities(final Campaign campaign, final Person person, final int expLvl) {
if (campaign.getCampaignOptions().isUseAbilities()) {
SingleSpecialAbilityGenerator singleSpecialAbilityGenerator = new SingleSpecialAbilityGenerator();
singleSpecialAbilityGenerator.setSkillPreferences(getSkillPreferences());
@@ -44,11 +48,21 @@ public boolean generateSpecialAbilities(final Campaign campaign, final Person pe
// Then we generate up to that number, stopping if there are no potential
// abilities to generate
- while ((numAbilities > 0)
- && singleSpecialAbilityGenerator.generateSpecialAbilities(campaign, person, expLvl)) {
+ while ((numAbilities > 0) &&
+ singleSpecialAbilityGenerator.generateSpecialAbilities(campaign, person, expLvl)) {
numAbilities--;
}
+ // Finally, we add any SPAs from the character's phenotype
+ Phenotype phenotype = person.getPhenotype();
+ if (phenotype != null) {
+ List bonusTraits = phenotype.getBonusTraits();
+
+ for (String bonusTrait : bonusTraits) {
+ person.getOptions().acquireAbility(LVL3_ADVANTAGES, bonusTrait, true);
+ }
+ }
+
return true;
}
From a0c7e5f909dfdd58e8b2566492b0e1b012f17168 Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Sun, 6 Apr 2025 02:15:58 -0500
Subject: [PATCH 04/10] - Consolidated basic and extra randomization under a
single streamlined condition block.
---
.../generator/DefaultSkillGenerator.java | 23 ++++++++-----------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
index d56464e4e55..93f815e54e4 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
@@ -174,27 +174,24 @@ public void generateAttributes(Person person) {
attributeModifier += phenotype.getAttributeModifier(attribute);
person.changeAttributeScore(attribute, attributeModifier);
- // Basic Attribute randomization
+ // Attribute randomization
int roll = d6();
if (roll == 1) {
person.changeAttributeScore(attribute, -1);
+
+ if (extraRandomAttributes) {
+ while ((d6() == 1) && (person.getAttributeScore(attribute) > MINIMUM_ATTRIBUTE_SCORE)) {
+ person.changeAttributeScore(attribute, -1);
+ }
+ }
} else if (roll == 6) {
person.changeAttributeScore(attribute, 1);
- }
-
- // Extra Attribute randomness
- if (extraRandomAttributes) {
- roll = d6();
- if (roll == 1) {
- do {
- person.changeAttributeScore(attribute, -1);
- } while ((d6() == 1) && (person.getAttributeScore(attribute) > MINIMUM_ATTRIBUTE_SCORE));
- } else if (roll == 6) {
- do {
+ if (extraRandomAttributes) {
+ while ((d6() == 6) && (person.getAttributeScore(attribute) < MAXIMUM_ATTRIBUTE_SCORE)) {
person.changeAttributeScore(attribute, 1);
- } while ((d6() == 1) && (person.getAttributeScore(attribute) < MAXIMUM_ATTRIBUTE_SCORE));
+ }
}
}
}
From ce079e3a5abbe09e7076fabcb7b42ecade76c348 Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Sun, 6 Apr 2025 17:26:16 -0500
Subject: [PATCH 05/10] - Replaced `getName` method calls with `getLabel` to
improve clarity and align with localized key usage. - Refactored and
standardized string formatting across affected files for improved
readability. - Removed hardcoded personnel role strings from
`Personnel.properties` and introduced `PersonnelRole.properties` to
centralize localization resources. - Replaced `parseFromString` method with
`fromString` for improved method naming and expanded functionality, including
handling deprecated names and case variations. - Added unit tests to validate
new `getLabel` functionality, `fromString` method, and missing resource keys
for roles. - Updated XML generation and parsing methods to utilize the new
role localization handling with `getLabel`.
---
.../mekhq/resources/Personnel.properties | 31 -
.../mekhq/resources/PersonnelRole.properties | 31 +
.../src/mekhq/campaign/MercRosterAccess.java | 230 +++--
.../campaign/market/PersonnelMarket.java | 69 +-
.../market/enums/UnitMarketRarity.java | 5 +-
.../src/mekhq/campaign/personnel/Person.java | 8 +-
.../personnel/enums/PersonnelRole.java | 360 ++++----
.../generator/RandomPortraitGenerator.java | 46 +-
.../campaign/report/PersonnelReport.java | 55 +-
.../storypoint/CreateCharacterStoryPoint.java | 33 +-
.../stratcon/StratconContractInitializer.java | 18 +-
MekHQ/src/mekhq/gui/CampaignGUI.java | 3 +-
.../immersiveDialogs/ImmersiveDialogCore.java | 4 +-
.../contents/AdvancementTab.java | 4 +-
MekHQ/src/mekhq/gui/dialog/BatchXPDialog.java | 2 +-
.../gui/dialog/HireBulkPersonnelDialog.java | 2 +-
.../gui/dialog/PersonnelMarketDialog.java | 131 +--
.../panels/CompanyGenerationOptionsPanel.java | 860 +++++++++---------
.../personnel/enums/PersonnelRoleTest.java | 83 +-
19 files changed, 1031 insertions(+), 944 deletions(-)
create mode 100644 MekHQ/resources/mekhq/resources/PersonnelRole.properties
diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties
index becaffe85b5..d1e4ca0607e 100644
--- a/MekHQ/resources/mekhq/resources/Personnel.properties
+++ b/MekHQ/resources/mekhq/resources/Personnel.properties
@@ -275,37 +275,6 @@ MergingSurnameStyle.FEMALE.dropDownText=Both share the female spouse's surname (
MergingSurnameStyle.WEIGHTED.text=Weighted
MergingSurnameStyle.WEIGHTED.toolTipText=The surname style used will be randomly determined through set weights
MergingSurnameStyle.WEIGHTED.dropDownText=Surname style randomly determined through set weights
-# PersonnelRole Enum
-PersonnelRole.MEKWARRIOR.text=MekWarrior
-PersonnelRole.LAM_PILOT.text=LAM Pilot
-PersonnelRole.GROUND_VEHICLE_DRIVER.text=Vehicle Driver
-PersonnelRole.NAVAL_VEHICLE_DRIVER.text=Naval Driver
-PersonnelRole.VTOL_PILOT.text=VTOL Pilot
-PersonnelRole.VEHICLE_GUNNER.text=Vehicle Gunner
-PersonnelRole.VEHICLE_CREW.text=Vehicle Crewmember
-PersonnelRole.AEROSPACE_PILOT.text=Aerospace Pilot
-PersonnelRole.CONVENTIONAL_AIRCRAFT_PILOT.text=Conventional Aircraft Pilot
-PersonnelRole.PROTOMEK_PILOT.text=ProtoMek Pilot
-PersonnelRole.BATTLE_ARMOUR.text=Battle Armor Pilot
-PersonnelRole.BATTLE_ARMOUR.clan.text=Elemental
-PersonnelRole.SOLDIER.text=Soldier
-PersonnelRole.VESSEL_PILOT.text=Vessel Pilot
-PersonnelRole.VESSEL_GUNNER.text=Vessel Gunner
-PersonnelRole.VESSEL_CREW.text=Vessel Crewmember
-PersonnelRole.VESSEL_NAVIGATOR.text=Hyperspace Navigator
-PersonnelRole.MEK_TECH.text=Mek Tech
-PersonnelRole.MECHANIC.text=Mechanic
-PersonnelRole.AERO_TEK.text=Aerospace Tech
-PersonnelRole.BA_TECH.text=Battle Armor Tech
-PersonnelRole.ASTECH.text=Astech
-PersonnelRole.DOCTOR.text=Doctor
-PersonnelRole.MEDIC.text=Medic
-PersonnelRole.ADMINISTRATOR_COMMAND.text=Admin/Command
-PersonnelRole.ADMINISTRATOR_LOGISTICS.text=Admin/Logistical
-PersonnelRole.ADMINISTRATOR_TRANSPORT.text=Admin/Transport
-PersonnelRole.ADMINISTRATOR_HR.text=Admin/HR
-PersonnelRole.DEPENDENT.text=Dependent
-PersonnelRole.NONE.text=None
# Profession Enum
Profession.MEKWARRIOR.text=MekWarrior
Profession.MEKWARRIOR.toolTipText=The MekWarrior Profession contains MekWarriors, LAM Pilots, and ProtoMek Pilots.
diff --git a/MekHQ/resources/mekhq/resources/PersonnelRole.properties b/MekHQ/resources/mekhq/resources/PersonnelRole.properties
new file mode 100644
index 00000000000..5195d5dd47a
--- /dev/null
+++ b/MekHQ/resources/mekhq/resources/PersonnelRole.properties
@@ -0,0 +1,31 @@
+# suppress inspection "UnusedProperty" for the whole file
+MEKWARRIOR.label=MekWarrior
+LAM_PILOT.label=LAM Pilot
+GROUND_VEHICLE_DRIVER.label=Vehicle Driver
+NAVAL_VEHICLE_DRIVER.label=Naval Driver
+VTOL_PILOT.label=VTOL Pilot
+VEHICLE_GUNNER.label=Vehicle Gunner
+VEHICLE_CREW.label=Vehicle Crewmember
+AEROSPACE_PILOT.label=Aerospace Pilot
+CONVENTIONAL_AIRCRAFT_PILOT.label=Conventional Aircraft Pilot
+PROTOMEK_PILOT.label=ProtoMek Pilot
+BATTLE_ARMOUR.label=Battle Armor Pilot
+BATTLE_ARMOUR.label.clan=Elemental
+SOLDIER.label=Soldier
+VESSEL_PILOT.label=Vessel Pilot
+VESSEL_GUNNER.label=Vessel Gunner
+VESSEL_CREW.label=Vessel Crewmember
+VESSEL_NAVIGATOR.label=Hyperspace Navigator
+MEK_TECH.label=Mek Tech
+MECHANIC.label=Mechanic
+AERO_TEK.label=Aerospace Tech
+BA_TECH.label=Battle Armor Tech
+ASTECH.label=Astech
+DOCTOR.label=Doctor
+MEDIC.label=Medic
+ADMINISTRATOR_COMMAND.label=Admin/Command
+ADMINISTRATOR_LOGISTICS.label=Admin/Logistical
+ADMINISTRATOR_TRANSPORT.label=Admin/Transport
+ADMINISTRATOR_HR.label=Admin/HR
+DEPENDENT.label=Dependent
+NONE.label=None
diff --git a/MekHQ/src/mekhq/campaign/MercRosterAccess.java b/MekHQ/src/mekhq/campaign/MercRosterAccess.java
index 0d9a974d6c8..9b0160b415c 100644
--- a/MekHQ/src/mekhq/campaign/MercRosterAccess.java
+++ b/MekHQ/src/mekhq/campaign/MercRosterAccess.java
@@ -46,8 +46,6 @@
import mekhq.campaign.force.Force;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.PersonnelOptions;
-import mekhq.campaign.personnel.skills.Skill;
-import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.campaign.personnel.enums.Profession;
import mekhq.campaign.personnel.ranks.Rank;
@@ -157,8 +155,9 @@ private void writeBasicData() {
statement.execute("TRUNCATE TABLE " + table + ".ranks");
int i = 0;
for (Rank rank : campaign.getRankSystem().getRanks()) {
- preparedStatement = connect
- .prepareStatement("INSERT INTO " + table + ".ranks (number, rankname) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".ranks (number, rankname) VALUES (?, ?)");
preparedStatement.setInt(1, i);
// TODO: This currently only exports MekWarrior Ranks. MercRoster software needs
// adjusted before this can be.
@@ -177,8 +176,9 @@ private void writeBasicData() {
try {
statement.execute("TRUNCATE TABLE " + table + ".skilltypes");
for (int i = 0; i < SkillType.skillList.length; i++) {
- preparedStatement = connect
- .prepareStatement("INSERT INTO " + table + ".skilltypes (name, shortname) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skilltypes (name, shortname) VALUES (?, ?)");
preparedStatement.setString(1, truncateString(SkillType.skillList[i], 60));
preparedStatement.setString(2, truncateString(getShortSkillName(SkillType.skillList[i]), 60));
preparedStatement.executeUpdate();
@@ -201,208 +201,237 @@ private void writeBasicData() {
int equipment = 0;
switch (role) {
case MEKWARRIOR:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_MEK));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_MEK));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case LAM_PILOT:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_MEK));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_MEK));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_AERO));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_AERO));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case GROUND_VEHICLE_DRIVER:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_GVEE));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case NAVAL_VEHICLE_DRIVER:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_NVEE));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case VTOL_PILOT:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_VTOL));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case VEHICLE_GUNNER:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_VEE));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case VEHICLE_CREW:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_TECH_MECHANIC));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case AEROSPACE_PILOT:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_AERO));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_AERO));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case CONVENTIONAL_AIRCRAFT_PILOT:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_JET));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_JET));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case PROTOMEK_PILOT:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_PROTO));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case BATTLE_ARMOUR:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_BA));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case SOLDIER:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_SMALL_ARMS));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case VESSEL_PILOT:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_PILOT_SPACE));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case VESSEL_GUNNER:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_GUN_SPACE));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case VESSEL_CREW:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_TECH_VESSEL));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case VESSEL_NAVIGATOR:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_NAV));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
equipment = 1;
break;
case MEK_TECH:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_TECH_MEK));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
break;
case AERO_TEK:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_TECH_AERO));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
break;
case MECHANIC:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_TECH_MECHANIC));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
break;
case BA_TECH:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_TECH_BA));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
break;
case ASTECH:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_ASTECH));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
break;
case DOCTOR:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_DOCTOR));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
break;
case MEDIC:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_MEDTECH));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
@@ -411,8 +440,9 @@ private void writeBasicData() {
case ADMINISTRATOR_HR:
case ADMINISTRATOR_LOGISTICS:
case ADMINISTRATOR_TRANSPORT:
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skillrequirements (skilltype, personneltype) VALUES (?, ?)");
preparedStatement.setInt(1, skillHash.get(SkillType.S_ADMIN));
preparedStatement.setInt(2, role.ordinal());
preparedStatement.executeUpdate();
@@ -422,9 +452,10 @@ private void writeBasicData() {
default:
break;
}
- preparedStatement = connect.prepareStatement("INSERT INTO " + table
- + ".crewtypes (type, squad, vehicletype, prefpos, equipment) VALUES (?, ?, ?, ?, ?)");
- preparedStatement.setString(1, truncateString(role.getName(campaign.getFaction().isClan()), 45));
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".crewtypes (type, squad, vehicletype, prefpos, equipment) VALUES (?, ?, ?, ?, ?)");
+ preparedStatement.setString(1, truncateString(role.getLabel(campaign.getFaction().isClan()), 45));
preparedStatement.setInt(2, 0);
preparedStatement.setInt(3, 1);
preparedStatement.setInt(4, role.ordinal());
@@ -448,8 +479,9 @@ private void writeBasicData() {
int weightstep = 5;
String weightscale = "ton";
// TODO: get these right for various unit types
- preparedStatement = connect.prepareStatement("INSERT INTO " + table
- + ".equipmenttypes (id, name, license, maxweight, minweight, weightstep, weightscale, prefpos, used, requirement) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".equipmenttypes (id, name, license, maxweight, minweight, weightstep, weightscale, prefpos, used, requirement) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
preparedStatement.setInt(1, i + 1);
preparedStatement.setString(2, truncateString(UnitType.getTypeDisplayableName(i), 45));
preparedStatement.setInt(3, i + 1);
@@ -474,8 +506,9 @@ private void writeForceData() {
// clear the table and re-enter a top level command
try {
statement.execute("TRUNCATE TABLE " + table + ".unit");
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".unit (type, name, parent, prefpos, text) VALUES (?, ?, ?, ?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".unit (type, name, parent, prefpos, text) VALUES (?, ?, ?, ?, ?)");
preparedStatement.setString(1, "1");
preparedStatement.setString(2, "Command");
preparedStatement.setInt(3, Integer.MAX_VALUE);
@@ -503,8 +536,9 @@ private void writeForceData() {
private void writeForce(Force force, int parent) {
try {
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".unit (type, name, parent, prefpos, text) VALUES (?, ?, ?, ?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".unit (type, name, parent, prefpos, text) VALUES (?, ?, ?, ?, ?)");
preparedStatement.setString(1, "1");
preparedStatement.setString(2, force.getName());
preparedStatement.setInt(3, parent);
@@ -563,8 +597,9 @@ private void writePersonnelData() {
forceId = forceHash.get(person.getId());
}
try {
- preparedStatement = connect.prepareStatement("UPDATE " + table
- + ".crew SET rank=?, lname=?, fname=?, callsign=?, status=?, parent=?, crewnumber=?, joiningdate=?, notes=?, bday=? WHERE uuid=?");
+ preparedStatement = connect.prepareStatement("UPDATE " +
+ table +
+ ".crew SET rank=?, lname=?, fname=?, callsign=?, status=?, parent=?, crewnumber=?, joiningdate=?, notes=?, bday=? WHERE uuid=?");
preparedStatement.setInt(1, person.getRankNumeric());
preparedStatement.setString(2, truncateString(person.getSurname(), 30));
preparedStatement.setString(3, truncateString(person.getGivenName(), 30));
@@ -580,8 +615,9 @@ private void writePersonnelData() {
preparedStatement.setString(11, person.getId().toString());
if (preparedStatement.executeUpdate() < 1) {
// no prior record so insert
- preparedStatement = connect.prepareStatement("INSERT INTO " + table
- + ".crew (rank, lname, fname, callsign, status, parent, crewnumber, joiningdate, notes, bday, uuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".crew (rank, lname, fname, callsign, status, parent, crewnumber, joiningdate, notes, bday, uuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
preparedStatement.setInt(1, person.getRankNumeric());
preparedStatement.setString(2, truncateString(person.getSurname(), 30));
preparedStatement.setString(3, truncateString(person.getGivenName(), 30));
@@ -606,8 +642,9 @@ private void writePersonnelData() {
// put id in a hash for equipment assignment
personHash.put(person.getId(), id);
// assign the personnel position
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".personnelpositions (personneltype, person) VALUES (?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".personnelpositions (personneltype, person) VALUES (?, ?)");
preparedStatement.setInt(1, person.getPrimaryRole().ordinal());
preparedStatement.setInt(2, id);
preparedStatement.executeUpdate();
@@ -617,8 +654,9 @@ private void writePersonnelData() {
for (int i = 0; i < SkillType.skillList.length; i++) {
if (person.hasSkill(SkillType.skillList[i])) {
Skill skill = person.getSkill(SkillType.skillList[i]);
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".skills (person, skill, value) VALUES (?, ?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".skills (person, skill, value) VALUES (?, ?, ?)");
preparedStatement.setInt(1, id);
preparedStatement.setInt(2, i + 1);
preparedStatement.setInt(3, skill.getFinalSkillValue(options, reputation));
@@ -629,8 +667,9 @@ private void writePersonnelData() {
// FIXME: the only issue here is we get duplicate kills for crewed vehicles
// TODO: clean up the getWhatKilled string
for (Kill k : campaign.getKillsFor(person.getId())) {
- preparedStatement = connect.prepareStatement(
- "INSERT INTO " + table + ".kills (parent, type, killdate, equipment) VALUES (?, ?, ?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".kills (parent, type, killdate, equipment) VALUES (?, ?, ?, ?)");
preparedStatement.setInt(1, id);
preparedStatement.setString(2, truncateString(k.getWhatKilled(), 45));
preparedStatement.setDate(3, Date.valueOf(k.getDate().toString()));
@@ -664,8 +703,9 @@ private void writeEquipmentData() {
determineProgress();
for (Unit u : campaign.getHangar().getUnits()) {
try {
- preparedStatement = connect.prepareStatement("UPDATE " + table
- + ".equipment SET type=?, name=?, subtype=?, crew=?, weight=?, regnumber=?, notes=? WHERE uuid=?");
+ preparedStatement = connect.prepareStatement("UPDATE " +
+ table +
+ ".equipment SET type=?, name=?, subtype=?, crew=?, weight=?, regnumber=?, notes=? WHERE uuid=?");
preparedStatement.setInt(1, u.getEntity().getUnitType() + 1);
preparedStatement.setString(2, truncateString(u.getEntity().getChassis(), 45));
preparedStatement.setString(3, truncateString(u.getEntity().getModel(), 45));
@@ -680,8 +720,9 @@ private void writeEquipmentData() {
preparedStatement.setString(8, u.getId().toString());
if (preparedStatement.executeUpdate() < 1) {
// no prior record so insert
- preparedStatement = connect.prepareStatement("INSERT INTO " + table
- + ".equipment (type, name, subtype, crew, weight, regnumber, notes, uuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+ preparedStatement = connect.prepareStatement("INSERT INTO " +
+ table +
+ ".equipment (type, name, subtype, crew, weight, regnumber, notes, uuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
preparedStatement.setInt(1, 1);
preparedStatement.setString(2, truncateString(u.getEntity().getChassis(), 45));
preparedStatement.setString(3, truncateString(u.getEntity().getModel(), 45));
@@ -757,10 +798,13 @@ public String getProgressNote() {
}
private int getLengthOfTask() {
- return 2 + campaign.getRankSystem().getRanks().size() + SkillType.skillList.length
- + PersonnelRole.values().length * 2 + UnitType.SIZE + campaign.getPersonnel().size() *
- +campaign.getHangar().getUnits().size()
- + campaign.getAllForces().size() * 2;
+ return 2 +
+ campaign.getRankSystem().getRanks().size() +
+ SkillType.skillList.length +
+ PersonnelRole.values().length * 2 +
+ UnitType.SIZE +
+ campaign.getPersonnel().size() * +campaign.getHangar().getUnits().size() +
+ campaign.getAllForces().size() * 2;
}
public void determineProgress() {
diff --git a/MekHQ/src/mekhq/campaign/market/PersonnelMarket.java b/MekHQ/src/mekhq/campaign/market/PersonnelMarket.java
index 0c374139dff..11c4011ba11 100644
--- a/MekHQ/src/mekhq/campaign/market/PersonnelMarket.java
+++ b/MekHQ/src/mekhq/campaign/market/PersonnelMarket.java
@@ -51,7 +51,6 @@
import mekhq.campaign.event.MarketNewPersonnelEvent;
import mekhq.campaign.event.OptionsChangedEvent;
import mekhq.campaign.personnel.Person;
-import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.rating.IUnitRating;
@@ -115,9 +114,9 @@ public void handleCampaignOptionsEvent(OptionsChangedEvent ev) {
}
/**
- * Generates new personnel for the current day, adding them to the campaign's personnel market if applicable.
- * The method handles removing outdated personnel, checking hiring hall and capital conditions,
- * and updating the personnel pool.
+ * Generates new personnel for the current day, adding them to the campaign's personnel market if applicable. The
+ * method handles removing outdated personnel, checking hiring hall and capital conditions, and updating the
+ * personnel pool.
*
* The process includes:
*
@@ -129,8 +128,8 @@ public void handleCampaignOptionsEvent(OptionsChangedEvent ev) {
*
Optionally generating a personnel market report, if this is enabled in campaign options.
*
*
- * @param campaign The {@link Campaign} related to the current gameplay context. Used to
- * determine the campaign's current planetary system, date, settings, factions, and more.
+ * @param campaign The {@link Campaign} related to the current gameplay context. Used to determine the campaign's
+ * current planetary system, date, settings, factions, and more.
*/
public void generatePersonnelForDay(Campaign campaign) {
PlanetarySystem location = campaign.getLocation().getCurrentSystem();
@@ -140,8 +139,9 @@ public void generatePersonnelForDay(Campaign campaign) {
boolean isOnPlanet = campaign.getLocation().isOnPlanet();
boolean useCapitalsHiringHallsOnly = campaign.getCampaignOptions().isUsePersonnelHireHiringHallOnly();
boolean isHiringHall = location.isHiringHall(today);
- boolean isCapital = location.getFactionSet(today).stream()
- .anyMatch(faction -> location.equals(faction.getStartingPlanet(campaign, today)));
+ boolean isCapital = location.getFactionSet(today)
+ .stream()
+ .anyMatch(faction -> location.equals(faction.getStartingPlanet(campaign, today)));
// Remove existing personnel for the day
if (!personnel.isEmpty()) {
@@ -181,9 +181,9 @@ public void generatePersonnelForDay(Campaign campaign) {
/**
* Generates and adds a report to the campaign about new personnel added to the personnel market.
*
- * If the corresponding option is enabled in the campaign settings, this function produces a detailed,
- * user-facing report about the most notable individual in the new personnel pool. The report includes
- * their experience level, primary role, and name.
+ * If the corresponding option is enabled in the campaign settings, this function produces a detailed, user-facing
+ * report about the most notable individual in the new personnel pool. The report includes their experience level,
+ * primary role, and name.
*
* The generated report is in HTML format and provides easy access to the personnel market interface.
*
@@ -208,13 +208,13 @@ private void generatePersonnelReport(Campaign campaign) {
}
report.append("")
- .append(SkillType.getColoredExperienceLevelName(experienceLevel))
- .append(' ')
- .append(person.getPrimaryRole())
- .append("")
- .append(" named ")
- .append(person.getFullName())
- .append(" is available.");
+ .append(SkillType.getColoredExperienceLevelName(experienceLevel))
+ .append(' ')
+ .append(person.getPrimaryRole())
+ .append("")
+ .append(" named ")
+ .append(person.getFullName())
+ .append(" is available.");
}
campaign.addReport(report.toString());
@@ -280,6 +280,7 @@ public void addAttachedEntity(UUID pid, Entity en) {
* Get the Entity associated with a recruit, if any
*
* @param p The recruit
+ *
* @return The Entity associated with the recruit, or null if there is none
*/
public Entity getAttachedEntity(Person p) {
@@ -290,6 +291,7 @@ public Entity getAttachedEntity(Person p) {
* Get the Entity associated with a recruit, if any
*
* @param pid The id of the recruit
+ *
* @return The Entity associated with the recruit, or null if there is none
*/
public Entity getAttachedEntity(UUID pid) {
@@ -337,8 +339,12 @@ public void writeToXML(final PrintWriter pw, int indent, final Campaign campaign
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "paidRecruitType", getPaidRecruitRole().name());
for (UUID id : attachedEntities.keySet()) {
- MHQXMLUtility.writeSimpleXMLAttributedTag(pw, indent, "entity", "id", id,
- attachedEntities.get(id).getShortNameRaw());
+ MHQXMLUtility.writeSimpleXMLAttributedTag(pw,
+ indent,
+ "entity",
+ "id",
+ id,
+ attachedEntities.get(id).getShortNameRaw());
}
MHQXMLUtility.writeSimpleXMLCloseTag(pw, --indent, "personnelMarket");
}
@@ -376,8 +382,12 @@ public static PersonnelMarket generateInstanceFromXML(Node wn, Campaign c, Versi
try {
en = new MekFileParser(ms.getSourceFile(), ms.getEntryName()).getEntity();
} catch (EntityLoadingException ex) {
- logger.error("Unable to load entity: " + ms.getSourceFile() + ": " + ms.getEntryName() + ": "
- + ex.getMessage(), ex);
+ logger.error("Unable to load entity: " +
+ ms.getSourceFile() +
+ ": " +
+ ms.getEntryName() +
+ ": " +
+ ex.getMessage(), ex);
}
if (null != en) {
retVal.attachedEntities.put(id, en);
@@ -385,7 +395,7 @@ public static PersonnelMarket generateInstanceFromXML(Node wn, Campaign c, Versi
} else if (wn2.getNodeName().equalsIgnoreCase("paidRecruitment")) {
retVal.paidRecruitment = true;
} else if (wn2.getNodeName().equalsIgnoreCase("paidRecruitType")) {
- retVal.setPaidRecruitRole(PersonnelRole.parseFromString(wn2.getTextContent().trim()));
+ retVal.setPaidRecruitRole(PersonnelRole.fromString(wn2.getTextContent().trim()));
} else if (null != retVal.method) {
retVal.method.loadFieldsFromXml(wn2);
} else {
@@ -467,8 +477,8 @@ public static long getUnitMainForceTypes(Campaign c) {
int sc = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_SMALL_CRAFT);
int cf = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_CONV_FIGHTER);
int asf = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_AEROSPACEFIGHTER);
- int vee = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_TANK, true)
- + hangarStats.getNumberOfUnitsByType(Entity.ETYPE_TANK);
+ int vee = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_TANK, true) +
+ hangarStats.getNumberOfUnitsByType(Entity.ETYPE_TANK);
int inf = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_INFANTRY);
int ba = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_BATTLEARMOR);
int proto = hangarStats.getNumberOfUnitsByType(Entity.ETYPE_PROTOMEK);
@@ -531,11 +541,12 @@ public static long getUnitMainForceTypes(Campaign c) {
public TargetRoll getShipSearchTarget(Campaign campaign, boolean jumpship) {
TargetRoll target = new TargetRoll(jumpship ? 12 : 10, "Base");
Person adminLog = campaign.findBestInRole(PersonnelRole.ADMINISTRATOR_LOGISTICS, SkillType.S_ADMIN);
- int adminLogExp = (adminLog == null) ? SkillType.EXP_ULTRA_GREEN
- : adminLog.getSkill(SkillType.S_ADMIN).getExperienceLevel();
+ int adminLogExp = (adminLog == null) ?
+ SkillType.EXP_ULTRA_GREEN :
+ adminLog.getSkill(SkillType.S_ADMIN).getExperienceLevel();
for (Person p : campaign.getAdmins()) {
- if ((p.getPrimaryRole().isAdministratorLogistics() || p.getSecondaryRole().isAdministratorLogistics())
- && p.getSkill(SkillType.S_ADMIN).getExperienceLevel() > adminLogExp) {
+ if ((p.getPrimaryRole().isAdministratorLogistics() || p.getSecondaryRole().isAdministratorLogistics()) &&
+ p.getSkill(SkillType.S_ADMIN).getExperienceLevel() > adminLogExp) {
adminLogExp = p.getSkill(SkillType.S_ADMIN).getExperienceLevel();
}
}
diff --git a/MekHQ/src/mekhq/campaign/market/enums/UnitMarketRarity.java b/MekHQ/src/mekhq/campaign/market/enums/UnitMarketRarity.java
index d11b6c359ce..7298e89376c 100644
--- a/MekHQ/src/mekhq/campaign/market/enums/UnitMarketRarity.java
+++ b/MekHQ/src/mekhq/campaign/market/enums/UnitMarketRarity.java
@@ -48,7 +48,7 @@ public enum UnitMarketRarity {
// region Constructors
UnitMarketRarity(final String name) {
final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Market",
- MekHQ.getMHQOptions().getLocale());
+ MekHQ.getMHQOptions().getLocale());
this.name = resources.getString(name);
}
// endregion Constructors
@@ -93,8 +93,7 @@ public static UnitMarketRarity parseFromString(final String text) {
case "3", "Common" -> COMMON;
case "4", "Very Common" -> VERY_COMMON;
default -> throw new IllegalStateException(
- "Unexpected value in mekhq/campaign/market/enums/UnitMarketRarity.java/parseFromString: "
- + text);
+ "Unexpected value in mekhq/campaign/market/enums/UnitMarketRarity.java/fromString: " + text);
};
}
// endregion File I/O
diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java
index b233c0645d1..17a1d6ee168 100644
--- a/MekHQ/src/mekhq/campaign/personnel/Person.java
+++ b/MekHQ/src/mekhq/campaign/personnel/Person.java
@@ -975,11 +975,11 @@ public String getPrimaryRoleDesc() {
if (isClanPersonnel()) {
bgPrefix = getPhenotype().getShortName() + ' ';
}
- return bgPrefix + getPrimaryRole().getName(isClanPersonnel());
+ return bgPrefix + getPrimaryRole().getLabel(isClanPersonnel());
}
public String getSecondaryRoleDesc() {
- return getSecondaryRole().getName(isClanPersonnel());
+ return getSecondaryRole().getLabel(isClanPersonnel());
}
public boolean canPerformRole(LocalDate today, final PersonnelRole role, final boolean primary) {
@@ -2677,10 +2677,10 @@ public static Person generateInstanceFromXML(Node wn, Campaign campaign, Version
} else if (nodeName.equalsIgnoreCase("biography")) {
person.biography = wn2.getTextContent();
} else if (nodeName.equalsIgnoreCase("primaryRole")) {
- final PersonnelRole primaryRole = PersonnelRole.parseFromString(wn2.getTextContent().trim());
+ final PersonnelRole primaryRole = PersonnelRole.fromString(wn2.getTextContent().trim());
person.setPrimaryRoleDirect(primaryRole);
} else if (nodeName.equalsIgnoreCase("secondaryRole")) {
- person.setSecondaryRoleDirect(PersonnelRole.parseFromString(wn2.getTextContent().trim()));
+ person.setSecondaryRoleDirect(PersonnelRole.fromString(wn2.getTextContent().trim()));
} else if (nodeName.equalsIgnoreCase("acquisitions")) {
person.acquisitions = MathUtility.parseInt(wn2.getTextContent());
} else if (nodeName.equalsIgnoreCase("primaryDesignator")) {
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
index d2e80c9e348..b629d9a3b1f 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
@@ -27,16 +27,16 @@
*/
package mekhq.campaign.personnel.enums;
+import static mekhq.utilities.MHQInternationalization.getFormattedTextAt;
+
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
-import java.util.ResourceBundle;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import megamek.common.annotations.Nullable;
+import megamek.codeUtilities.MathUtility;
import megamek.logging.MMLogger;
-import mekhq.MekHQ;
import mekhq.campaign.personnel.skills.enums.SkillAttribute;
/**
@@ -47,50 +47,115 @@ public enum PersonnelRole {
// region Enum Declarations
/**
* Individual roles with corresponding name texts and mnemonics.
+ *
+ *
Note: The attribute score modifiers assume a default attribute score of 5. I opted to only include
+ * this information as modifiers, as it means if we ever change what the default score is, the ratios will remain
+ * correct.
*/
- MEKWARRIOR("PersonnelRole.MEKWARRIOR.text", KeyEvent.VK_M),
- LAM_PILOT("PersonnelRole.LAM_PILOT.text", KeyEvent.VK_UNDEFINED),
- GROUND_VEHICLE_DRIVER("PersonnelRole.GROUND_VEHICLE_DRIVER.text", KeyEvent.VK_V),
- NAVAL_VEHICLE_DRIVER("PersonnelRole.NAVAL_VEHICLE_DRIVER.text", KeyEvent.VK_N),
- VTOL_PILOT("PersonnelRole.VTOL_PILOT.text", KeyEvent.VK_UNDEFINED),
- VEHICLE_GUNNER("PersonnelRole.VEHICLE_GUNNER.text", KeyEvent.VK_G),
- VEHICLE_CREW("PersonnelRole.VEHICLE_CREW.text", KeyEvent.VK_UNDEFINED),
- AEROSPACE_PILOT("PersonnelRole.AEROSPACE_PILOT.text", KeyEvent.VK_A),
- CONVENTIONAL_AIRCRAFT_PILOT("PersonnelRole.CONVENTIONAL_AIRCRAFT_PILOT.text", KeyEvent.VK_C),
- PROTOMEK_PILOT("PersonnelRole.PROTOMEK_PILOT.text", KeyEvent.VK_P),
- BATTLE_ARMOUR("PersonnelRole.BATTLE_ARMOUR.text",
- "PersonnelRole.BATTLE_ARMOUR.clan.text",
- KeyEvent.VK_B,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0),
- SOLDIER("PersonnelRole.SOLDIER.text", KeyEvent.VK_S),
- VESSEL_PILOT("PersonnelRole.VESSEL_PILOT.text", KeyEvent.VK_I),
- VESSEL_GUNNER("PersonnelRole.VESSEL_GUNNER.text", KeyEvent.VK_U),
- VESSEL_CREW("PersonnelRole.VESSEL_CREW.text", KeyEvent.VK_W),
- VESSEL_NAVIGATOR("PersonnelRole.VESSEL_NAVIGATOR.text", KeyEvent.VK_Y),
- MEK_TECH("PersonnelRole.MEK_TECH.text", KeyEvent.VK_T),
- MECHANIC("PersonnelRole.MECHANIC.text", KeyEvent.VK_E),
- AERO_TEK("PersonnelRole.AERO_TEK.text", KeyEvent.VK_O),
- BA_TECH("PersonnelRole.BA_TECH.text", KeyEvent.VK_UNDEFINED),
- ASTECH("PersonnelRole.ASTECH.text", KeyEvent.VK_UNDEFINED),
- DOCTOR("PersonnelRole.DOCTOR.text", KeyEvent.VK_D),
- MEDIC("PersonnelRole.MEDIC.text", KeyEvent.VK_UNDEFINED),
- ADMINISTRATOR_COMMAND("PersonnelRole.ADMINISTRATOR_COMMAND.text", KeyEvent.VK_UNDEFINED),
- ADMINISTRATOR_LOGISTICS("PersonnelRole.ADMINISTRATOR_LOGISTICS.text", KeyEvent.VK_L),
- ADMINISTRATOR_TRANSPORT("PersonnelRole.ADMINISTRATOR_TRANSPORT.text", KeyEvent.VK_R),
- ADMINISTRATOR_HR("PersonnelRole.ADMINISTRATOR_HR.text", KeyEvent.VK_H),
- DEPENDENT("PersonnelRole.DEPENDENT.text", KeyEvent.VK_UNDEFINED),
- NONE("PersonnelRole.NONE.text", KeyEvent.VK_UNDEFINED);
+ // I used an average of the modifiers from the MekWarrior, Hot Shot, and Grizzled Veteran ATOW Archetypes
+ MEKWARRIOR(true, KeyEvent.VK_M, -1, 0, 1, 1, -1, -1, -1),
+
+ // I used an average of the modifiers from the MekWarrior, and Aerospace Pilot ATOW Archetypes
+ LAM_PILOT(true, KeyEvent.VK_UNDEFINED, -1, -1, 1, 1, -1, -1, -1),
+
+ // ATOW: Tanker Archetype
+ GROUND_VEHICLE_DRIVER(true, KeyEvent.VK_V, -1, 0, 0, +1, -1, -1, -1),
+
+ // ATOW: Tanker Archetype
+ NAVAL_VEHICLE_DRIVER(true, KeyEvent.VK_N, -1, 0, 0, +1, -1, -1, -1),
+
+ // ATOW: Companion Chopper Pilot Archetype
+ VTOL_PILOT(true, KeyEvent.VK_UNDEFINED, -1, -1, 0, 0, -1, -1, -1),
+
+ // ATOW: Tanker Archetype
+ VEHICLE_GUNNER(true, KeyEvent.VK_G, -1, 0, 0, +1, -1, -1, -1),
+
+ // ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
+ // Technician skill)
+ VEHICLE_CREW(true, KeyEvent.VK_UNDEFINED, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Aerospace Pilot Archetype
+ AEROSPACE_PILOT(true, KeyEvent.VK_A, -3, -2, 0, 0, -1, -1, 0),
+
+ // ATOW: Aerospace Pilot Archetype
+ CONVENTIONAL_AIRCRAFT_PILOT(true, KeyEvent.VK_C, -3, -2, 0, 0, -1, -1, 0),
+
+ // ATOW: Aerospace Pilot Archetype (most ProtoMek pilots are Aerospace Sibkbo washouts, so this made the most sense)
+ PROTOMEK_PILOT(true, KeyEvent.VK_P, -3, -2, 0, 0, -1, -1, 0),
+
+ // ATOW: Elemental Archetype
+ BATTLE_ARMOUR(true, true, KeyEvent.VK_B, +2, +1, -1, 0, -2, -1, -2),
+
+ // ATOW: Renegade Warrior Archetype
+ SOLDIER(true, KeyEvent.VK_S, 0, 0, -1, 0, -1, +1, -2),
+
+ // ATOW: Tanker Archetype
+ VESSEL_PILOT(true, KeyEvent.VK_I, -1, 0, 0, +1, -1, -1, -1),
+
+ // ATOW: Tanker Archetype
+ VESSEL_GUNNER(true, KeyEvent.VK_U, -1, 0, 0, +1, -1, -1, -1),
+
+ // ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
+ // Technician skill)
+ VESSEL_CREW(true, KeyEvent.VK_W, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Battlefield Tech Archetype
+ VESSEL_NAVIGATOR(true, KeyEvent.VK_Y, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
+ // Technician skill)
+ MEK_TECH(false, KeyEvent.VK_T, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
+ // Technician skill)
+ MECHANIC(false, KeyEvent.VK_E, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
+ // Technician skill)
+ AERO_TEK(false, KeyEvent.VK_O, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
+ // Technician skill)
+ BA_TECH(false, KeyEvent.VK_UNDEFINED, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
+ // Technician skill)
+ ASTECH(false, KeyEvent.VK_UNDEFINED, 0, -1, 0, -2, 0, -1, -2),
+
+ // ATOW: Communications Specialist Archetype (this might seem like an odd choice, but the Attributes for this Archetype
+ // work really well for this profession
+ DOCTOR(false, KeyEvent.VK_D, -2, -1, -1, 0, 1, -1, -1),
+
+ // ATOW: Communications Specialist Archetype (this might seem like an odd choice, but the Attributes for this Archetype
+ // work really well for this profession
+ MEDIC(false, KeyEvent.VK_UNDEFINED, -2, -1, -1, 0, 1, -1, -1),
+
+ // ATOW: Faceman Archetype
+ ADMINISTRATOR_COMMAND(false, KeyEvent.VK_UNDEFINED, -2, -2, -2, -1, 1, -2, 1),
+
+ // ATOW: Faceman Archetype
+ ADMINISTRATOR_LOGISTICS(false, KeyEvent.VK_L, -2, -2, -2, -1, 1, -2, 1),
+
+ // ATOW: Faceman Archetype
+ ADMINISTRATOR_TRANSPORT(false, KeyEvent.VK_R, -2, -2, -2, -1, 1, -2, 1),
+
+ // ATOW: Faceman Archetype
+ ADMINISTRATOR_HR(false, KeyEvent.VK_H, -2, -2, -2, -1, 1, -2, 1),
+
+ // No archetype, but ATOW pg 35 states that the Attribute scores for an average person are 4
+ DEPENDENT(false, KeyEvent.VK_UNDEFINED, -1, -1, -1, -1, -1, -1, -1),
+
+ // If we're generating a character without a Profession, we're just going to leave them with middle of the road
+ // Attribute scores (5 in everything)
+ NONE(KeyEvent.VK_UNDEFINED);
// endregion Enum Declarations
// region Variable Declarations
- private final String name;
- private final String clanName;
+ private static final MMLogger logger = MMLogger.create(PersonnelRole.class);
+ private static final String RESOURCE_BUNDLE = "mekhq.resources." + PersonnelRole.class.getSimpleName();
+
+ private final boolean isCombat;
+ private final boolean hasClanName;
private final int mnemonic; // Unused: J, K, Q, X, Z
private final int strength;
private final int body;
@@ -102,37 +167,25 @@ public enum PersonnelRole {
// endregion Variable Declarations
// region Constructors
+ PersonnelRole(final int mnemonic) {
+ this(false, false, mnemonic, 0, 0, 0, 0, 0, 0, 0);
+ }
- /**
- * Constructs a new PersonnelRole with the given name and mnemonic.
- *
- * @param name the name of the personnel role
- * @param mnemonic the mnemonic of the personnel role
- */
- PersonnelRole(final String name, final int mnemonic) {
- this(name, null, mnemonic, 0, 0, 0, 0, 0, 0, 0);
+ PersonnelRole(final boolean isCombat, final int mnemonic, final int strength, final int body, final int dexterity,
+ final int reflexes, final int intelligence, final int willpower, final int charisma) {
+ this(isCombat, false, mnemonic, strength, body, dexterity, reflexes, intelligence, willpower, charisma);
}
- /**
- * Main constructor that initializes the role with name, clanName, and mnemonic. ClanName is optional and defaults
- * to name if {@code null}.
- *
- * @param name the name of the role.
- * @param clanName the clan name of the role can be {@code null}.
- * @param mnemonic the mnemonic associated with the role.
- */
- PersonnelRole(final String name, @Nullable final String clanName, final int mnemonic, final int strength,
- final int body, final int reflexes, final int dexterity, final int intelligence, final int willpower,
+ PersonnelRole(final boolean isCombat, final boolean hasClanName, final int mnemonic, final int strength,
+ final int body, final int dexterity, final int reflexes, final int intelligence, final int willpower,
final int charisma) {
- final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel",
- MekHQ.getMHQOptions().getLocale());
- this.name = resources.getString(name);
- this.clanName = (clanName == null) ? this.name : resources.getString(clanName);
+ this.isCombat = isCombat;
+ this.hasClanName = hasClanName;
this.mnemonic = mnemonic;
this.strength = strength;
this.body = body;
- this.reflexes = reflexes;
this.dexterity = dexterity;
+ this.reflexes = reflexes;
this.intelligence = intelligence;
this.willpower = willpower;
this.charisma = charisma;
@@ -140,8 +193,34 @@ public enum PersonnelRole {
// endregion Constructors
// region Getters
+
+ /**
+ * @deprecated use {@link #getLabel(boolean)} instead
+ */
+ @Deprecated(since = "0.50.05", forRemoval = true)
public String getName(final boolean isClan) {
- return isClan ? clanName : name;
+ return getLabel(isClan);
+ }
+
+ /**
+ * Retrieves the label for this instance, optionally using a clan-specific label if applicable.
+ *
+ *
This method generates a label based on a specific resource bundle key. If the specified
+ * option to use a clan label is enabled and a clan name is available, it retrieves the clan-specific label.
+ * Otherwise, it retrieves the standard label.
+ *
+ * @param isClan A flag indicating whether to use the clan-specific label. If {@code true} and the instance has a
+ * clan name, the clan-specific label will be used.
+ *
+ * @return The formatted label string, either clan-specific or standard, based on the provided flag and
+ * availability.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public String getLabel(final boolean isClan) {
+ final boolean useClan = isClan && hasClanName;
+ return getFormattedTextAt(RESOURCE_BUNDLE, name() + ".label" + (useClan ? ".clan" : ""));
}
public int getMnemonic() {
@@ -395,25 +474,7 @@ public boolean isNone() {
* @return {@code true} if the character has a combat role, {@code true} otherwise.
*/
public boolean isCombat() {
- return switch (this) {
- case MEKWARRIOR,
- LAM_PILOT,
- GROUND_VEHICLE_DRIVER,
- NAVAL_VEHICLE_DRIVER,
- VTOL_PILOT,
- VEHICLE_GUNNER,
- VEHICLE_CREW,
- AEROSPACE_PILOT,
- CONVENTIONAL_AIRCRAFT_PILOT,
- PROTOMEK_PILOT,
- BATTLE_ARMOUR,
- SOLDIER,
- VESSEL_PILOT,
- VESSEL_GUNNER,
- VESSEL_CREW,
- VESSEL_NAVIGATOR -> true;
- default -> false;
- };
+ return isCombat;
}
/**
@@ -635,87 +696,65 @@ public static int getCivilianCount() {
}
// endregion Static Methods
+ // region File I/O
+
/**
- * Parses a string representation of a {@link PersonnelRole} and returns the corresponding enum value.
+ * @deprecated use {@link #fromString(String)} instead.
+ */
+ @Deprecated(since = "0.50.05", forRemoval = true)
+ public static PersonnelRole parseFromString(final String personnelRole) {
+ return fromString(personnelRole);
+ }
+
+ /**
+ * Converts a given string into a {@code PersonnelRole}.
+ *
+ *
This method attempts to parse the input string into a {@code PersonnelRole} using a series of steps:
+ *
+ *
+ *
If the input is {@code null} or blank, the method logs an error and returns {@code NONE}.
+ *
Tries to parse the input as an enum name by converting it to uppercase and replacing spaces with underscores.
+ *
Attempts to match the input string with the labels of available {@code PersonnelRole} values, both standard and clan-specific.
+ *
Includes compatibility handling for versions earlier than 50.1 with specific string mappings.
+ *
Finally, tries to parse the input as an ordinal value of the enum.
+ *
If all attempts fail, the method logs an error and returns {@code NONE}.
+ *
*
- * @param personnelRole the string representation of the {@link PersonnelRole}
+ * @param text The input string to be converted into a {@code PersonnelRole}.
*
- * @return the corresponding {@link PersonnelRole} enum value, or {@code NONE} if parsing fails
+ * @return The corresponding {@code PersonnelRole} if successfully parsed, or {@code NONE} if parsing fails.
+ *
+ * @author Illiani
+ * @since 0.50.5
*/
- // region File I/O
- public static PersonnelRole parseFromString(final String personnelRole) {
+ public static PersonnelRole fromString(String text) {
+ if (text == null || text.isBlank()) {
+ logger.error("Unable to parse text into a PersonnelRole. Returning NONE");
+ return NONE;
+ }
+
+ // Parse from name
try {
- return valueOf(personnelRole);
+ return PersonnelRole.valueOf(text.toUpperCase().replace(" ", "_"));
} catch (Exception ignored) {
}
- // Magic Number Save Format
+ // Parse from label
try {
- switch (Integer.parseInt(personnelRole)) {
- case 0:
- return NONE;
- case 1:
- return MEKWARRIOR;
- case 2:
- return AEROSPACE_PILOT;
- case 3:
- return GROUND_VEHICLE_DRIVER;
- case 4:
- return NAVAL_VEHICLE_DRIVER;
- case 5:
- return VTOL_PILOT;
- case 6:
- return VEHICLE_GUNNER;
- case 7:
- return BATTLE_ARMOUR;
- case 8:
- return SOLDIER;
- case 9:
- return PROTOMEK_PILOT;
- case 10:
- return CONVENTIONAL_AIRCRAFT_PILOT;
- case 11:
- return VESSEL_PILOT;
- case 12:
- return VESSEL_CREW;
- case 13:
- return VESSEL_GUNNER;
- case 14:
- return VESSEL_NAVIGATOR;
- case 15:
- return MEK_TECH;
- case 16:
- return MECHANIC;
- case 17:
- return AERO_TEK;
- case 18:
- return BA_TECH;
- case 19:
- return ASTECH;
- case 20:
- return DOCTOR;
- case 21:
- return MEDIC;
- case 22:
- return ADMINISTRATOR_COMMAND;
- case 23:
- return ADMINISTRATOR_LOGISTICS;
- case 24:
- return ADMINISTRATOR_TRANSPORT;
- case 25:
- return ADMINISTRATOR_HR;
- case 26:
- return LAM_PILOT;
- case 27:
- return VEHICLE_CREW;
- default:
- break;
+ for (PersonnelRole personnelRole : PersonnelRole.values()) {
+ if (personnelRole.getLabel(false).equalsIgnoreCase(text)) {
+ return personnelRole;
+ }
+
+ if (personnelRole.getLabel(true).equalsIgnoreCase(text)) {
+ return personnelRole;
+ }
}
} catch (Exception ignored) {
}
// <50.1 compatibility
- switch (personnelRole) {
+ switch (text.toUpperCase().replace(" ", "_")) {
case "MECHWARRIOR" -> {
return MEKWARRIOR;
}
@@ -732,12 +771,13 @@ public static PersonnelRole parseFromString(final String personnelRole) {
}
}
- // Error report, if parsing fails.
- // Ignore IDEA's suggestion of concatenating the error log, as this
- // functionality doesn't
- // exist within MMLogger
- MMLogger.create(PersonnelRole.class)
- .error("Unable to parse {} into a PersonnelRole. Returning {}.", personnelRole, NONE);
+ // Parse from ordinal
+ try {
+ return PersonnelRole.values()[MathUtility.parseInt(text, NONE.ordinal())];
+ } catch (Exception ignored) {
+ }
+
+ logger.error("Unable to parse {} into a PersonnelRole. Returning NONE", text);
return NONE;
}
// endregion File I/O
@@ -749,6 +789,6 @@ public static PersonnelRole parseFromString(final String personnelRole) {
*/
@Override
public String toString() {
- return name;
+ return getLabel(false);
}
}
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/RandomPortraitGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/RandomPortraitGenerator.java
index c633981c0a7..b9685181893 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/RandomPortraitGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/RandomPortraitGenerator.java
@@ -27,15 +27,20 @@
*/
package mekhq.campaign.personnel.generator;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
import megamek.common.Compute;
import megamek.common.icons.Portrait;
import megamek.logging.MMLogger;
import mekhq.MHQStaticDirectoryManager;
import mekhq.campaign.personnel.Person;
-import java.io.File;
-import java.util.*;
-
public class RandomPortraitGenerator {
private static final MMLogger logger = MMLogger.create(RandomPortraitGenerator.class);
@@ -46,20 +51,20 @@ private RandomPortraitGenerator() {
/**
* This generates a unique Portrait based on the supplied {@link Person}
*
- * @param personnel a list of all personnel, from which existing portraits are
- * determined
+ * @param personnel a list of all personnel, from which existing portraits are determined
* @param p the {@link Person} to generate a unique portrait for
+ *
* @return the generated portrait
*/
- public static Portrait generate(Collection personnel, Person p,
- Boolean allowDuplicatePortraits) {
+ public static Portrait generate(Collection personnel, Person p, Boolean allowDuplicatePortraits) {
// first create a list of existing portrait strings, so we can check for
// duplicates - unless they are allowed in campaign options
Set existingPortraits = new HashSet<>();
if (!allowDuplicatePortraits) {
for (Person existingPerson : personnel) {
- existingPortraits.add(existingPerson.getPortrait().getCategory() + ':'
- + existingPerson.getPortrait().getFilename());
+ existingPortraits.add(existingPerson.getPortrait().getCategory() +
+ ':' +
+ existingPerson.getPortrait().getFilename());
}
}
@@ -69,7 +74,7 @@ public static Portrait generate(Collection personnel, Person p,
// and if none are found then /gender/rolegroup, then /gender/combat or
// /gender/support, then in /gender.
File genderFile = new File(p.getGender().isFemale() ? "Female" : "Male");
- File searchFile = new File(genderFile, p.getPrimaryRole().getName(p.isClanPersonnel()));
+ File searchFile = new File(genderFile, p.getPrimaryRole().getLabel(p.isClanPersonnel()));
possiblePortraits = getPossibleRandomPortraits(existingPortraits, searchFile);
@@ -108,29 +113,30 @@ public static Portrait generate(Collection personnel, Person p,
if (temp.length == 2) {
return new Portrait(temp[0], temp[1]);
} else {
- logger.error("Failed to generate portrait for " + p.getFullTitle() + ". "
- + chosenPortrait + " does not split into an array of length 2.");
+ logger.error("Failed to generate portrait for " +
+ p.getFullTitle() +
+ ". " +
+ chosenPortrait +
+ " does not split into an array of length 2.");
}
} else {
- logger.warn("Failed to generate portrait for " + p.getFullTitle()
- + ". No possible portraits found.");
+ logger.warn("Failed to generate portrait for " + p.getFullTitle() + ". No possible portraits found.");
}
return new Portrait();
}
/**
- * This is a helper method that determines what possible unassigned portraits
- * can be generated
- * based on the supplied subdirectory
+ * This is a helper method that determines what possible unassigned portraits can be generated based on the supplied
+ * subdirectory
*
- * @param existingPortraits the list of existing portraits that have already
- * been assigned
+ * @param existingPortraits the list of existing portraits that have already been assigned
* @param subdirectory the subdirectory to search
+ *
* @return a list of all possible unassigned random portraits
*/
private static List getPossibleRandomPortraits(final Set existingPortraits,
- final File subdirectory) {
+ final File subdirectory) {
if (MHQStaticDirectoryManager.getPortraits() == null) {
return new ArrayList<>();
}
diff --git a/MekHQ/src/mekhq/campaign/report/PersonnelReport.java b/MekHQ/src/mekhq/campaign/report/PersonnelReport.java
index 1a7dbca7f27..effe6fcc1a0 100644
--- a/MekHQ/src/mekhq/campaign/report/PersonnelReport.java
+++ b/MekHQ/src/mekhq/campaign/report/PersonnelReport.java
@@ -63,8 +63,7 @@ public String getCombatPersonnelDetails() {
if (p.getStatus().isActive()) {
countPersonByType[p.getPrimaryRole().ordinal()]++;
countTotal++;
- if (getCampaign().getCampaignOptions().isUseAdvancedMedical()
- && !p.getInjuries().isEmpty()) {
+ if (getCampaign().getCampaignOptions().isUseAdvancedMedical() && !p.getInjuries().isEmpty()) {
countInjured++;
} else if (p.getHits() > 0) {
countInjured++;
@@ -93,18 +92,20 @@ public String getCombatPersonnelDetails() {
for (PersonnelRole role : personnelRoles) {
if (role.isCombat()) {
- sb.append(String.format(" %-30s %4s\n", role.getName(getCampaign().getFaction().isClan()),
- countPersonByType[role.ordinal()]));
+ sb.append(String.format(" %-30s %4s\n",
+ role.getLabel(getCampaign().getFaction().isClan()),
+ countPersonByType[role.ordinal()]));
}
}
sb.append('\n')
- .append(String.format("%-30s %4s\n", "Injured Combat Personnel", countInjured))
- .append(String.format("%-30s %4s\n", "MIA Combat Personnel", countMIA))
- .append(String.format("%-30s %4s\n", "KIA Combat Personnel", countKIA))
- .append(String.format("%-30s %4s\n", "Retired Combat Personnel", countRetired))
- .append(String.format("%-30s %4s\n", "Dead Combat Personnel", countDead))
- .append("\nMonthly Salary For Combat Personnel: ").append(salary.toAmountAndSymbolString());
+ .append(String.format("%-30s %4s\n", "Injured Combat Personnel", countInjured))
+ .append(String.format("%-30s %4s\n", "MIA Combat Personnel", countMIA))
+ .append(String.format("%-30s %4s\n", "KIA Combat Personnel", countKIA))
+ .append(String.format("%-30s %4s\n", "Retired Combat Personnel", countRetired))
+ .append(String.format("%-30s %4s\n", "Dead Combat Personnel", countDead))
+ .append("\nMonthly Salary For Combat Personnel: ")
+ .append(salary.toAmountAndSymbolString());
return sb.toString();
}
@@ -160,10 +161,12 @@ public String getSupportPersonnelDetails() {
}
//Add Salaries of Temp Workers
- salary = salary.plus(getCampaign().getCampaignOptions().getRoleBaseSalaries()[PersonnelRole.ASTECH.ordinal()].getAmount().doubleValue()
- * getCampaign().getAstechPool());
- salary = salary.plus(getCampaign().getCampaignOptions().getRoleBaseSalaries()[PersonnelRole.MEDIC.ordinal()].getAmount().doubleValue()
- * getCampaign().getMedicPool());
+ salary = salary.plus(getCampaign().getCampaignOptions()
+ .getRoleBaseSalaries()[PersonnelRole.ASTECH.ordinal()].getAmount().doubleValue() *
+ getCampaign().getAstechPool());
+ salary = salary.plus(getCampaign().getCampaignOptions()
+ .getRoleBaseSalaries()[PersonnelRole.MEDIC.ordinal()].getAmount().doubleValue() *
+ getCampaign().getMedicPool());
StringBuilder sb = new StringBuilder("Support Personnel\n\n");
@@ -171,8 +174,9 @@ public String getSupportPersonnelDetails() {
for (PersonnelRole role : personnelRoles) {
if (role.isSupport(true)) {
- sb.append(String.format(" %-30s %4s\n", role.getName(getCampaign().getFaction().isClan()),
- countPersonByType[role.ordinal()]));
+ sb.append(String.format(" %-30s %4s\n",
+ role.getLabel(getCampaign().getFaction().isClan()),
+ countPersonByType[role.ordinal()]));
}
}
@@ -181,15 +185,16 @@ public String getSupportPersonnelDetails() {
sb.append(String.format(" %-30s %4s\n", "Temp Astechs", getCampaign().getAstechPool()));
sb.append('\n')
- .append(String.format("%-30s %4s\n", "Injured Support Personnel", countInjured))
- .append(String.format("%-30s %4s\n", "MIA Support Personnel", countMIA))
- .append(String.format("%-30s %4s\n", "KIA Support Personnel", countKIA))
- .append(String.format("%-30s %4s\n", "Retired Support Personnel", countRetired))
- .append(String.format("%-30s %4s\n", "Dead Support Personnel", countDead))
- .append("\nMonthly Salary For Support Personnel: ").append(salary.toAmountAndSymbolString())
- .append(String.format("\nYou have " + dependents + " %s", (dependents == 1) ? "dependent" : "dependents"))
- .append(String.format("\nYou have " + prisoners + " prisoner%s", prisoners == 1 ? "" : "s"))
- .append(String.format("\nYou have " + bondsmen + " %s", (bondsmen == 1) ? "bondsman" : "bondsmen"));
+ .append(String.format("%-30s %4s\n", "Injured Support Personnel", countInjured))
+ .append(String.format("%-30s %4s\n", "MIA Support Personnel", countMIA))
+ .append(String.format("%-30s %4s\n", "KIA Support Personnel", countKIA))
+ .append(String.format("%-30s %4s\n", "Retired Support Personnel", countRetired))
+ .append(String.format("%-30s %4s\n", "Dead Support Personnel", countDead))
+ .append("\nMonthly Salary For Support Personnel: ")
+ .append(salary.toAmountAndSymbolString())
+ .append(String.format("\nYou have " + dependents + " %s", (dependents == 1) ? "dependent" : "dependents"))
+ .append(String.format("\nYou have " + prisoners + " prisoner%s", prisoners == 1 ? "" : "s"))
+ .append(String.format("\nYou have " + bondsmen + " %s", (bondsmen == 1) ? "bondsman" : "bondsmen"));
return sb.toString();
}
diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java
index 57dfba2c3b5..2e87f1933aa 100644
--- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java
+++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java
@@ -44,7 +44,6 @@
import mekhq.campaign.force.Force;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.PersonnelOptions;
-import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.personnel.backgrounds.BackgroundsController;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.campaign.personnel.enums.Phenotype;
@@ -61,10 +60,8 @@
import org.w3c.dom.NodeList;
/**
- * This StoryPoint opens a {@link CreateCharacterDialog CreateCharacterDialog}
- * which allows a player to create a new
- * character. Various initial values can be set, as well as an initial
- * experience point pool. Additionally, the ability
+ * This StoryPoint opens a {@link CreateCharacterDialog CreateCharacterDialog} which allows a player to create a new
+ * character. Various initial values can be set, as well as an initial experience point pool. Additionally, the ability
* to edit certain parts of the character can be restricted.
*/
public class CreateCharacterStoryPoint extends StoryPoint {
@@ -88,8 +85,7 @@ public class CreateCharacterStoryPoint extends StoryPoint {
private int edge;
/**
- * The id of the person in the campaign. This will otherwise be set randomly. By
- * setting it manually we can
+ * The id of the person in the campaign. This will otherwise be set randomly. By setting it manually we can
* reference it later.
*/
private UUID personId;
@@ -219,9 +215,17 @@ public Person createPerson() {
public void start() {
super.start();
Person person = createPerson();
- final CreateCharacterDialog personDialog = new CreateCharacterDialog(null, true, person,
- getCampaign(), xpPool, instructions, editOrigin, editBirthday, editGender, nameRestrictions,
- limitFaction);
+ final CreateCharacterDialog personDialog = new CreateCharacterDialog(null,
+ true,
+ person,
+ getCampaign(),
+ xpPool,
+ instructions,
+ editOrigin,
+ editBirthday,
+ editGender,
+ nameRestrictions,
+ limitFaction);
getCampaign().importPerson(person);
personDialog.setVisible(true);
if (null != assignedUnitId) {
@@ -244,8 +248,7 @@ private void setEdgeTriggers(Person p) {
// role at the moment
PersonnelOptions options = p.getOptions();
- for (Enumeration i = options.getGroups(); i
- .hasMoreElements();) {
+ for (Enumeration i = options.getGroups(); i.hasMoreElements(); ) {
IOptionGroup group = i.nextElement();
if (!group.getKey().equalsIgnoreCase(PersonnelOptions.EDGE_ADVANTAGES)) {
@@ -253,7 +256,7 @@ private void setEdgeTriggers(Person p) {
}
IOption option;
- for (Enumeration j = group.getOptions(); j.hasMoreElements();) {
+ for (Enumeration j = group.getOptions(); j.hasMoreElements(); ) {
option = j.nextElement();
if (null != option && option.getType() == IOption.BOOLEAN) {
p.setEdgeTrigger(option.getName(), true);
@@ -319,9 +322,9 @@ protected void loadFieldsFromXmlNode(Node wn, Campaign c, Version version) throw
} else if (wn2.getNodeName().equalsIgnoreCase("commander")) {
commander = Boolean.parseBoolean(wn2.getTextContent().trim());
} else if (wn2.getNodeName().equalsIgnoreCase("primaryRole")) {
- primaryRole = PersonnelRole.parseFromString(wn2.getTextContent().trim());
+ primaryRole = PersonnelRole.fromString(wn2.getTextContent().trim());
} else if (wn2.getNodeName().equalsIgnoreCase("phenotype")) {
- phenotype = Phenotype.parseFromString(wn2.getTextContent().trim());
+ phenotype = Phenotype.fromString(wn2.getTextContent().trim());
} else if (wn2.getNodeName().equalsIgnoreCase("faction")) {
faction = Factions.getInstance().getFaction(wn2.getTextContent().trim());
} else if (wn2.getNodeName().equalsIgnoreCase("editOrigin")) {
diff --git a/MekHQ/src/mekhq/campaign/stratcon/StratconContractInitializer.java b/MekHQ/src/mekhq/campaign/stratcon/StratconContractInitializer.java
index 6c042738b7f..bbba5ce0040 100644
--- a/MekHQ/src/mekhq/campaign/stratcon/StratconContractInitializer.java
+++ b/MekHQ/src/mekhq/campaign/stratcon/StratconContractInitializer.java
@@ -65,7 +65,8 @@ public class StratconContractInitializer {
/**
* Initializes the campaign state given a contract, campaign and contract definition
*/
- public static void initializeCampaignState(AtBContract contract, Campaign campaign, StratconContractDefinition contractDefinition) {
+ public static void initializeCampaignState(AtBContract contract, Campaign campaign,
+ StratconContractDefinition contractDefinition) {
StratconCampaignState campaignState = new StratconCampaignState(contract);
campaignState.setBriefingText(contractDefinition.getBriefing() +
" " +
@@ -272,7 +273,7 @@ public static void initializeCampaignState(AtBContract contract, Campaign campai
//
// if (hiddenCache != null) {
// logger.info(String.format("A secret cache has been spawned for contract %s",
- // contract.getName()));
+ // contract.getLabel()));
// }
// } else {
// logger.error("'Chasing a Rumor' scenario failed to deserialize");
@@ -286,7 +287,8 @@ public static void initializeCampaignState(AtBContract contract, Campaign campai
/**
* Set up initial state of a track, dimensions are based on number of assigned lances.
*/
- public static StratconTrackState initializeTrackState(int numLances, int scenarioOdds, int deploymentTime, int planetaryTemp) {
+ public static StratconTrackState initializeTrackState(int numLances, int scenarioOdds, int deploymentTime,
+ int planetaryTemp) {
// to initialize a track,
// 1. we set the # of required lances
// 2. set the track size to a total of numlances * 28 hexes, a rectangle that is
@@ -350,7 +352,8 @@ private static List trackObjectDistribution(int numObjects, int numTrac
* Avoids places with existing facilities and scenarios, capable of taking facility sub set and setting strategic
* objective flag.
*/
- private static void initializeTrackFacilities(StratconTrackState trackState, int numFacilities, ForceAlignment owner, boolean strategicObjective, List modifiers) {
+ private static void initializeTrackFacilities(StratconTrackState trackState, int numFacilities,
+ ForceAlignment owner, boolean strategicObjective, List modifiers) {
int trackSize = trackState.getWidth() * trackState.getHeight();
@@ -424,7 +427,9 @@ private static void initializeTrackFacilities(StratconTrackState trackState, int
* @param objectiveModifiers a list of optional {@link String} modifiers to apply to the generated scenarios; can be
* {@code null} if no modifiers are required
*/
- private static void initializeObjectiveScenarios(Campaign campaign, AtBContract contract, StratconTrackState trackState, int numScenarios, List objectiveScenarios, List objectiveModifiers) {
+ private static void initializeObjectiveScenarios(Campaign campaign, AtBContract contract,
+ StratconTrackState trackState, int numScenarios, List objectiveScenarios,
+ List objectiveModifiers) {
// pick scenario from subset
// place it on the map somewhere nothing else has been placed yet
// if it's a facility scenario, place the facility
@@ -551,7 +556,8 @@ private static void initializeObjectiveScenarios(Campaign campaign, AtBContract
* @return a {@link StratconCoords} object representing the location of a suitable, unoccupied coordinate, or
* {@code null} if no valid coordinates are available
*/
- public static @Nullable StratconCoords getUnoccupiedCoords(StratconTrackState trackState, boolean allowPlayerFacilities, boolean allowPlayerForces, boolean emphasizeStrategicTargets) {
+ public static @Nullable StratconCoords getUnoccupiedCoords(StratconTrackState trackState,
+ boolean allowPlayerFacilities, boolean allowPlayerForces, boolean emphasizeStrategicTargets) {
final int trackHeight = trackState.getHeight();
final int trackWidth = trackState.getWidth();
diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java
index 3200ae13635..b63ac121737 100644
--- a/MekHQ/src/mekhq/gui/CampaignGUI.java
+++ b/MekHQ/src/mekhq/gui/CampaignGUI.java
@@ -92,7 +92,6 @@
import mekhq.campaign.parts.Refit;
import mekhq.campaign.parts.enums.PartQuality;
import mekhq.campaign.personnel.Person;
-import mekhq.campaign.personnel.skills.SkillType;
import mekhq.campaign.personnel.autoAwards.AutoAwardsController;
import mekhq.campaign.personnel.divorce.RandomDivorce;
import mekhq.campaign.personnel.enums.PersonnelRole;
@@ -750,7 +749,7 @@ private void initMenu() {
JMenu menuHire = new JMenu(resourceMap.getString("menuHire.text"));
menuHire.setMnemonic(KeyEvent.VK_H);
for (PersonnelRole role : PersonnelRole.getPrimaryRoles()) {
- JMenuItem miHire = new JMenuItem(role.getName(getCampaign().getFaction().isClan()));
+ JMenuItem miHire = new JMenuItem(role.getLabel(getCampaign().getFaction().isClan()));
if (role.getMnemonic() != KeyEvent.VK_UNDEFINED) {
miHire.setMnemonic(role.getMnemonic());
miHire.setAccelerator(KeyStroke.getKeyStroke(role.getMnemonic(), InputEvent.ALT_DOWN_MASK));
diff --git a/MekHQ/src/mekhq/gui/baseComponents/immersiveDialogs/ImmersiveDialogCore.java b/MekHQ/src/mekhq/gui/baseComponents/immersiveDialogs/ImmersiveDialogCore.java
index fd54260a82a..c5df439b9e8 100644
--- a/MekHQ/src/mekhq/gui/baseComponents/immersiveDialogs/ImmersiveDialogCore.java
+++ b/MekHQ/src/mekhq/gui/baseComponents/immersiveDialogs/ImmersiveDialogCore.java
@@ -664,12 +664,12 @@ public static StringBuilder getSpeakerDescription(Campaign campaign, Person spea
PersonnelRole primaryRole = speaker.getPrimaryRole();
if (!primaryRole.isNone()) {
- speakerDescription.append(" ").append(primaryRole.getName(isClan));
+ speakerDescription.append(" ").append(primaryRole.getLabel(isClan));
}
PersonnelRole secondaryRole = speaker.getSecondaryRole();
if (!secondaryRole.isNone()) {
- speakerDescription.append(" ").append(secondaryRole.getName(isClan));
+ speakerDescription.append(" ").append(secondaryRole.getLabel(isClan));
}
Unit assignedUnit = speaker.getUnit();
diff --git a/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java b/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java
index 78e5869069e..96556ad8cee 100644
--- a/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java
+++ b/MekHQ/src/mekhq/gui/campaignOptions/contents/AdvancementTab.java
@@ -1034,7 +1034,7 @@ private JPanel createRecruitmentBonusesCombatPanel() {
layout.gridx = currentColumn * 2;
layout.gridy = currentRow;
- lblRecruitmentBonusCombat[i] = new JLabel(roles.get(i).getName(false));
+ lblRecruitmentBonusCombat[i] = new JLabel(roles.get(i).getLabel(false));
spnRecruitmentBonusCombat[i] = new JSpinner(new SpinnerNumberModel(0, -12, 12, 1));
panel.add(lblRecruitmentBonusCombat[i], layout);
@@ -1076,7 +1076,7 @@ private JPanel createRecruitmentBonusesSupportPanel() {
layout.gridx = currentColumn * 2;
layout.gridy = currentRow;
- lblRecruitmentBonusSupport[i] = new JLabel(roles.get(i).getName(false));
+ lblRecruitmentBonusSupport[i] = new JLabel(roles.get(i).getLabel(false));
spnRecruitmentBonusSupport[i] = new JSpinner(new SpinnerNumberModel(0, -12, 12, 1));
panel.add(lblRecruitmentBonusSupport[i], layout);
diff --git a/MekHQ/src/mekhq/gui/dialog/BatchXPDialog.java b/MekHQ/src/mekhq/gui/dialog/BatchXPDialog.java
index dd03e44ecdb..192ec12e91c 100644
--- a/MekHQ/src/mekhq/gui/dialog/BatchXPDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/BatchXPDialog.java
@@ -170,7 +170,7 @@ private JComponent getButtonPanel() {
personTypeModel.addElement(new PersonTypeItem(resourceMap.getString("primaryRole.choice.text"), null));
final PersonnelRole[] personnelRoles = PersonnelRole.values();
for (PersonnelRole personnelRole : personnelRoles) {
- personTypeModel.addElement(new PersonTypeItem(personnelRole.getName(campaign.getFaction().isClan()),
+ personTypeModel.addElement(new PersonTypeItem(personnelRole.getLabel(campaign.getFaction().isClan()),
personnelRole.ordinal()));
}
choiceType.setModel(personTypeModel);
diff --git a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java
index ffda6c9e165..78741fc80e7 100644
--- a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java
@@ -134,7 +134,7 @@ private void initComponents() {
DefaultComboBoxModel personTypeModel = new DefaultComboBoxModel<>();
for (final PersonnelRole personnelRole : PersonnelRole.getPrimaryRoles()) {
- personTypeModel.addElement(new PersonTypeItem(personnelRole.getName(campaign.getFaction().isClan()),
+ personTypeModel.addElement(new PersonTypeItem(personnelRole.getLabel(campaign.getFaction().isClan()),
personnelRole));
}
choiceType.setModel(personTypeModel);
diff --git a/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java b/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java
index d98c8b10e93..b29f9b159f9 100644
--- a/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/PersonnelMarketDialog.java
@@ -89,26 +89,26 @@ public class PersonnelMarketDialog extends JDialog {
// region Variable Declarations
private PersonnelTableModel personnelModel;
- private Campaign campaign;
- private CampaignGUI hqView;
- private PersonnelMarket personnelMarket;
- private Person selectedPerson = null;
- private Money unitCost = Money.zero();
-
- private JComboBox comboPersonType;
- private JLabel lblPersonChoice;
- private JRadioButton radioNormalRoll;
- private JRadioButton radioPaidRecruitment;
- private JComboBox comboRecruitRole;
- private JPanel panelOKBtns;
- private JPanel panelMain;
- private JPanel panelFilterBtns;
- private JTable tablePersonnel;
- private JLabel lblUnitCost;
- private JScrollPane scrollTablePersonnel;
- private JScrollPane scrollPersonnelView;
+ private Campaign campaign;
+ private CampaignGUI hqView;
+ private PersonnelMarket personnelMarket;
+ private Person selectedPerson = null;
+ private Money unitCost = Money.zero();
+
+ private JComboBox comboPersonType;
+ private JLabel lblPersonChoice;
+ private JRadioButton radioNormalRoll;
+ private JRadioButton radioPaidRecruitment;
+ private JComboBox comboRecruitRole;
+ private JPanel panelOKBtns;
+ private JPanel panelMain;
+ private JPanel panelFilterBtns;
+ private JTable tablePersonnel;
+ private JLabel lblUnitCost;
+ private JScrollPane scrollTablePersonnel;
+ private JScrollPane scrollPersonnelView;
private TableRowSorter sorter;
- private JSplitPane splitMain;
+ private JSplitPane splitMain;
private final List personnelMarketColumns = List.of(PersonnelTableModelColumn.FIRST_NAME,
PersonnelTableModelColumn.LAST_NAME,
@@ -125,10 +125,10 @@ public class PersonnelMarketDialog extends JDialog {
public PersonnelMarketDialog(final JFrame frame, final CampaignGUI view, final Campaign campaign) {
super(frame, true);
- hqView = view;
- this.campaign = campaign;
+ hqView = view;
+ this.campaign = campaign;
personnelMarket = campaign.getPersonnelMarket();
- personnelModel = new PersonnelTableModel(campaign);
+ personnelModel = new PersonnelTableModel(campaign);
personnelModel.setData(personnelMarket.getPersonnel());
personnelModel.loadAssignmentFromMarket(personnelMarket);
initComponents();
@@ -139,17 +139,17 @@ public PersonnelMarketDialog(final JFrame frame, final CampaignGUI view, final C
private void initComponents() {
scrollTablePersonnel = new JScrollPaneWithSpeed();
- scrollPersonnelView = new JScrollPaneWithSpeed();
- tablePersonnel = new JTable();
- panelMain = new JPanel();
- panelFilterBtns = new JPanel();
- comboPersonType = new JComboBox<>();
- radioNormalRoll = new JRadioButton();
+ scrollPersonnelView = new JScrollPaneWithSpeed();
+ tablePersonnel = new JTable();
+ panelMain = new JPanel();
+ panelFilterBtns = new JPanel();
+ comboPersonType = new JComboBox<>();
+ radioNormalRoll = new JRadioButton();
radioPaidRecruitment = new JRadioButton();
- lblUnitCost = new JLabel();
- panelOKBtns = new JPanel();
- lblPersonChoice = new JLabel();
- comboRecruitRole = new JComboBox<>(PersonnelRole.values());
+ lblUnitCost = new JLabel();
+ panelOKBtns = new JPanel();
+ lblPersonChoice = new JLabel();
+ comboRecruitRole = new JComboBox<>(PersonnelRole.values());
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Personnel Market");
@@ -168,11 +168,11 @@ public void windowClosing(WindowEvent e) {
lblPersonChoice.setText("Personnel Type:");
lblPersonChoice.setName("lblPersonChoice");
GridBagConstraints gridBagConstraints = new GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 0.0;
- gridBagConstraints.anchor = GridBagConstraints.WEST;
- gridBagConstraints.insets = new Insets(5, 5, 5, 5);
+ gridBagConstraints.anchor = GridBagConstraints.WEST;
+ gridBagConstraints.insets = new Insets(5, 5, 5, 5);
panelFilterBtns.add(lblPersonChoice, gridBagConstraints);
DefaultComboBoxModel personTypeModel = new DefaultComboBoxModel<>();
@@ -185,28 +185,28 @@ public void windowClosing(WindowEvent e) {
comboPersonType.setName("comboUnitType");
comboPersonType.setPreferredSize(new Dimension(200, 27));
comboPersonType.addActionListener(evt -> filterPersonnel());
- gridBagConstraints = new GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 0;
+ gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = GridBagConstraints.WEST;
panelFilterBtns.add(comboPersonType, gridBagConstraints);
- boolean atbOutofContract = campaign.getCampaignOptions().isUseAtB() && !campaign.hasActiveContract();
+ boolean atbOutofContract = campaign.getCampaignOptions().isUseAtB() && !campaign.hasActiveContract();
boolean usingCamOpsMarkets = campaign.getCampaignOptions().getPersonnelMarketName().equals("Campaign Ops");
if (atbOutofContract && !usingCamOpsMarkets) {
// Paid recruitment is available
radioNormalRoll.setText("Make normal roll next week");
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
- gridBagConstraints.anchor = GridBagConstraints.WEST;
+ gridBagConstraints.anchor = GridBagConstraints.WEST;
panelFilterBtns.add(radioNormalRoll, gridBagConstraints);
radioPaidRecruitment.setText("Make paid recruitment roll next week (100,000 C-bills)");
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 2;
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
gridBagConstraints.gridwidth = 2;
- gridBagConstraints.anchor = GridBagConstraints.WEST;
+ gridBagConstraints.anchor = GridBagConstraints.WEST;
panelFilterBtns.add(radioPaidRecruitment, gridBagConstraints);
ButtonGroup group = new ButtonGroup();
@@ -221,18 +221,19 @@ public void windowClosing(WindowEvent e) {
final boolean isClan = campaign.getFaction().isClan();
comboRecruitRole.setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(JList> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ public Component getListCellRendererComponent(JList> list, Object value, int index,
+ boolean isSelected, boolean cellHasFocus) {
return super.getListCellRendererComponent(list,
- (value instanceof PersonnelRole) ? ((PersonnelRole) value).getName(isClan) : value,
+ (value instanceof PersonnelRole) ? ((PersonnelRole) value).getLabel(isClan) : value,
index,
isSelected,
cellHasFocus);
}
});
- gridBagConstraints.gridx = 2;
- gridBagConstraints.gridy = 2;
+ gridBagConstraints.gridx = 2;
+ gridBagConstraints.gridy = 2;
gridBagConstraints.gridwidth = 1;
- gridBagConstraints.anchor = GridBagConstraints.WEST;
+ gridBagConstraints.anchor = GridBagConstraints.WEST;
panelFilterBtns.add(comboRecruitRole, gridBagConstraints);
if (personnelMarket.getPaidRecruitment()) {
@@ -261,8 +262,8 @@ public Component getListCellRendererComponent(JList> list, Object value, int i
sorter = new TableRowSorter<>(personnelModel);
- final XTableColumnModel columnModel = (XTableColumnModel) tablePersonnel.getColumnModel();
- final ArrayList sortKeys = new ArrayList<>();
+ final XTableColumnModel columnModel = (XTableColumnModel) tablePersonnel.getColumnModel();
+ final ArrayList sortKeys = new ArrayList<>();
for (final PersonnelTableModelColumn column : PersonnelTableModel.PERSONNEL_COLUMNS) {
final TableColumn tableColumn = columnModel.getColumnByModelIndex(column.ordinal());
if (!personnelMarketColumns.contains(column)) {
@@ -383,8 +384,8 @@ private void hirePerson(ActionEvent evt) {
selectedPerson.getSalary(campaign).multipliedBy(2) :
Money.zero()).plus(unitCost))) {
campaign.addReport("Insufficient funds. Transaction cancelled.");
+ MekHQ.getMHQOptions().getFontColorNegativeHexColor() +
+ "'>Insufficient funds. Transaction cancelled.");
} else {
/*
* Adding person to campaign changes pid; grab the old one to
@@ -407,8 +408,8 @@ private void hirePerson(ActionEvent evt) {
private void addPerson() {
if (selectedPerson != null) {
- Entity en = personnelMarket.getAttachedEntity(selectedPerson);
- UUID pid = selectedPerson.getId();
+ Entity en = personnelMarket.getAttachedEntity(selectedPerson);
+ UUID pid = selectedPerson.getId();
if (campaign.recruitPerson(selectedPerson, true)) {
addUnit(en, false);
@@ -426,11 +427,11 @@ private void addUnit(Entity en, boolean pay) {
}
if (pay &&
- !campaign.getFinances()
- .debit(TransactionType.UNIT_PURCHASE,
- campaign.getLocalDate(),
- unitCost,
- "Purchased " + en.getShortName())) {
+ !campaign.getFinances()
+ .debit(TransactionType.UNIT_PURCHASE,
+ campaign.getLocalDate(),
+ unitCost,
+ "Purchased " + en.getShortName())) {
return;
}
@@ -513,7 +514,7 @@ private void personChanged(ListSelectionEvent evt) {
unitCost = Money.zero();
} else {
if (!campaign.getCampaignOptions().isUseShareSystem() &&
- ((en instanceof Mek) || (en instanceof Tank) || (en instanceof Aero))) {
+ ((en instanceof Mek) || (en instanceof Tank) || (en instanceof Aero))) {
unitCost = Money.of(en.getCost(false)).dividedBy(2.0);
} else {
unitCost = Money.zero();
@@ -532,7 +533,7 @@ void refreshPersonView() {
return;
}
- Entity en = personnelMarket.getAttachedEntity(selectedPerson);
+ Entity en = personnelMarket.getAttachedEntity(selectedPerson);
String unitText = "";
if (unitCost.isPositive()) {
unitText = "Unit cost: " + unitCost.toAmountAndSymbolString();
@@ -552,7 +553,7 @@ void refreshPersonView() {
if (null != en) {
JTabbedPane tabUnit = new JTabbedPane();
- String name = "Commander";
+ String name = "Commander";
if (Compute.getFullCrewSize(en) == 1) {
name = "Pilot";
}
diff --git a/MekHQ/src/mekhq/gui/panels/CompanyGenerationOptionsPanel.java b/MekHQ/src/mekhq/gui/panels/CompanyGenerationOptionsPanel.java
index 4a3b3837e3d..4e9e212e59d 100644
--- a/MekHQ/src/mekhq/gui/panels/CompanyGenerationOptionsPanel.java
+++ b/MekHQ/src/mekhq/gui/panels/CompanyGenerationOptionsPanel.java
@@ -36,7 +36,6 @@
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TreeMap;
-
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JSpinner.NumberEditor;
@@ -164,7 +163,7 @@ public class CompanyGenerationOptionsPanel extends AbstractMHQScrollablePanel {
// region Constructors
public CompanyGenerationOptionsPanel(final JFrame frame, final Campaign campaign,
- final @Nullable CompanyGenerationOptions companyGenerationOptions) {
+ final @Nullable CompanyGenerationOptions companyGenerationOptions) {
super(frame, "CompanyGenerationOptionsPanel", new GridBagLayout());
this.campaign = campaign;
setTracksViewportWidth(false);
@@ -190,7 +189,7 @@ public MMComboBox getComboCompanyGenerationMethod() {
}
public void setComboCompanyGenerationMethod(
- final MMComboBox comboCompanyGenerationMethod) {
+ final MMComboBox comboCompanyGenerationMethod) {
this.comboCompanyGenerationMethod = comboCompanyGenerationMethod;
}
@@ -257,8 +256,8 @@ public JLabel getLblTotalSupportPersonnel() {
}
public void updateLblTotalSupportPersonnel(final int numSupportPersonnel) {
- getLblTotalSupportPersonnel().setText(String.format(
- resources.getString("lblTotalSupportPersonnel.text"), numSupportPersonnel));
+ getLblTotalSupportPersonnel().setText(String.format(resources.getString("lblTotalSupportPersonnel.text"),
+ numSupportPersonnel));
}
public void setLblTotalSupportPersonnel(final JLabel lblTotalSupportPersonnel) {
@@ -318,7 +317,7 @@ public JCheckBox getChkPrioritizeCompanyCommanderCombatSkills() {
}
public void setChkPrioritizeCompanyCommanderCombatSkills(
- final JCheckBox chkPrioritizeCompanyCommanderCombatSkills) {
+ final JCheckBox chkPrioritizeCompanyCommanderCombatSkills) {
this.chkPrioritizeCompanyCommanderCombatSkills = chkPrioritizeCompanyCommanderCombatSkills;
}
@@ -429,7 +428,7 @@ public MMComboBox getComboBattleMekFactionGene
}
public void setComboBattleMekFactionGenerationMethod(
- final MMComboBox comboBattleMekFactionGenerationMethod) {
+ final MMComboBox comboBattleMekFactionGenerationMethod) {
this.comboBattleMekFactionGenerationMethod = comboBattleMekFactionGenerationMethod;
}
@@ -438,7 +437,7 @@ public MMComboBox getComboBattleMekWeightC
}
public void setComboBattleMekWeightClassGenerationMethod(
- final MMComboBox comboBattleMekWeightClassGenerationMethod) {
+ final MMComboBox comboBattleMekWeightClassGenerationMethod) {
this.comboBattleMekWeightClassGenerationMethod = comboBattleMekWeightClassGenerationMethod;
}
@@ -447,7 +446,7 @@ public MMComboBox getComboBattleMekQualityGene
}
public void setComboBattleMekQualityGenerationMethod(
- final MMComboBox comboBattleMekQualityGenerationMethod) {
+ final MMComboBox comboBattleMekQualityGenerationMethod) {
this.comboBattleMekQualityGenerationMethod = comboBattleMekQualityGenerationMethod;
}
@@ -554,7 +553,7 @@ public JCheckBox getChkUseSpecifiedFactionToGenerateForceIcons() {
}
public void setChkUseSpecifiedFactionToGenerateForceIcons(
- final JCheckBox chkUseSpecifiedFactionToGenerateForceIcons) {
+ final JCheckBox chkUseSpecifiedFactionToGenerateForceIcons) {
this.chkUseSpecifiedFactionToGenerateForceIcons = chkUseSpecifiedFactionToGenerateForceIcons;
}
@@ -637,7 +636,7 @@ public JCheckBox getChkGenerateFractionalMachineGunAmmunition() {
}
public void setChkGenerateFractionalMachineGunAmmunition(
- final JCheckBox chkGenerateFractionalMachineGunAmmunition) {
+ final JCheckBox chkGenerateFractionalMachineGunAmmunition) {
this.chkGenerateFractionalMachineGunAmmunition = chkGenerateFractionalMachineGunAmmunition;
}
// endregion Spares
@@ -795,9 +794,9 @@ public void setChkGenerateMysteryBoxTypes(final Map c
// region Determination Methods
public int determineMaximumSupportPersonnel() {
- return ((getChkGenerateMercenaryCompanyCommandLance().isSelected() ? 1 : 0)
- + ((int) getSpnCompanyCount().getValue() * (int) getSpnLancesPerCompany().getValue())
- + (int) getSpnIndividualLanceCount().getValue()) * (int) getSpnLanceSize().getValue();
+ return ((getChkGenerateMercenaryCompanyCommandLance().isSelected() ? 1 : 0) +
+ ((int) getSpnCompanyCount().getValue() * (int) getSpnLancesPerCompany().getValue()) +
+ (int) getSpnIndividualLanceCount().getValue()) * (int) getSpnLanceSize().getValue();
}
// endregion Determination Methods
@@ -849,14 +848,13 @@ private JPanel createBaseInformationPanel() {
lblCompanyGenerationMethod.setToolTipText(resources.getString("lblCompanyGenerationMethod.toolTipText"));
lblCompanyGenerationMethod.setName("lblCompanyGenerationMethod");
- setComboCompanyGenerationMethod(
- new MMComboBox<>("comboCompanyGenerationMethod", CompanyGenerationMethod.values()));
+ setComboCompanyGenerationMethod(new MMComboBox<>("comboCompanyGenerationMethod",
+ CompanyGenerationMethod.values()));
getComboCompanyGenerationMethod().setToolTipText(resources.getString("lblCompanyGenerationMethod.toolTipText"));
getComboCompanyGenerationMethod().setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(final JList> list, final Object value,
- final int index, final boolean isSelected,
- final boolean cellHasFocus) {
+ public Component getListCellRendererComponent(final JList> list, final Object value, final int index,
+ final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof CompanyGenerationMethod) {
list.setToolTipText(((CompanyGenerationMethod) value).getToolTipText());
@@ -870,16 +868,16 @@ public Component getListCellRendererComponent(final JList> list, final Object
lblSpecifiedFaction.setName("lblSpecifiedFaction");
final DefaultComboBoxModel specifiedFactionModel = new DefaultComboBoxModel<>();
- specifiedFactionModel.addAll(FactionDisplay
- .getSortedValidFactionDisplays(Factions.getInstance().getChoosableFactions(),
- getCampaign().getLocalDate()));
+ specifiedFactionModel.addAll(FactionDisplay.getSortedValidFactionDisplays(Factions.getInstance()
+ .getChoosableFactions(),
+ getCampaign().getLocalDate()));
setComboSpecifiedFaction(new MMComboBox<>("comboFaction", specifiedFactionModel));
getComboSpecifiedFaction().setToolTipText(resources.getString("lblSpecifiedFaction.toolTipText"));
- setChkGenerateMercenaryCompanyCommandLance(
- new JCheckBox(resources.getString("chkGenerateMercenaryCompanyCommandLance.text")));
- getChkGenerateMercenaryCompanyCommandLance()
- .setToolTipText(resources.getString("chkGenerateMercenaryCompanyCommandLance.toolTipText"));
+ setChkGenerateMercenaryCompanyCommandLance(new JCheckBox(resources.getString(
+ "chkGenerateMercenaryCompanyCommandLance.text")));
+ getChkGenerateMercenaryCompanyCommandLance().setToolTipText(resources.getString(
+ "chkGenerateMercenaryCompanyCommandLance.toolTipText"));
getChkGenerateMercenaryCompanyCommandLance().setName("chkGenerateMercenaryCompanyCommandLance");
final JLabel lblCompanyCount = new JLabel(resources.getString("lblCompanyCount.text"));
@@ -942,51 +940,50 @@ public Component getListCellRendererComponent(final JList> list, final Object
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblCompanyGenerationMethod)
- .addComponent(getComboCompanyGenerationMethod(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblSpecifiedFaction)
- .addComponent(getComboSpecifiedFaction(), Alignment.LEADING))
- .addComponent(getChkGenerateMercenaryCompanyCommandLance())
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblCompanyCount)
- .addComponent(getSpnCompanyCount())
- .addComponent(lblIndividualLanceCount)
- .addComponent(getSpnIndividualLanceCount(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblLancesPerCompany)
- .addComponent(getSpnLancesPerCompany())
- .addComponent(lblLanceSize)
- .addComponent(getSpnLanceSize(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblStarLeagueYear)
- .addComponent(getSpnStarLeagueYear(), Alignment.LEADING)));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblCompanyGenerationMethod)
- .addComponent(getComboCompanyGenerationMethod()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblSpecifiedFaction)
- .addComponent(getComboSpecifiedFaction()))
- .addComponent(getChkGenerateMercenaryCompanyCommandLance())
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblCompanyCount)
- .addComponent(getSpnCompanyCount())
- .addComponent(lblIndividualLanceCount)
- .addComponent(getSpnIndividualLanceCount()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblLancesPerCompany)
- .addComponent(getSpnLancesPerCompany())
- .addComponent(lblLanceSize)
- .addComponent(getSpnLanceSize()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblStarLeagueYear)
- .addComponent(getSpnStarLeagueYear())));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblCompanyGenerationMethod)
+ .addComponent(getComboCompanyGenerationMethod(),
+ Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblSpecifiedFaction)
+ .addComponent(getComboSpecifiedFaction(), Alignment.LEADING))
+ .addComponent(getChkGenerateMercenaryCompanyCommandLance())
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblCompanyCount)
+ .addComponent(getSpnCompanyCount())
+ .addComponent(lblIndividualLanceCount)
+ .addComponent(getSpnIndividualLanceCount(), Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblLancesPerCompany)
+ .addComponent(getSpnLancesPerCompany())
+ .addComponent(lblLanceSize)
+ .addComponent(getSpnLanceSize(), Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblStarLeagueYear)
+ .addComponent(getSpnStarLeagueYear(), Alignment.LEADING)));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblCompanyGenerationMethod)
+ .addComponent(getComboCompanyGenerationMethod()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblSpecifiedFaction)
+ .addComponent(getComboSpecifiedFaction()))
+ .addComponent(getChkGenerateMercenaryCompanyCommandLance())
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblCompanyCount)
+ .addComponent(getSpnCompanyCount())
+ .addComponent(lblIndividualLanceCount)
+ .addComponent(getSpnIndividualLanceCount()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblLancesPerCompany)
+ .addComponent(getSpnLancesPerCompany())
+ .addComponent(lblLanceSize)
+ .addComponent(getSpnLanceSize()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblStarLeagueYear)
+ .addComponent(getSpnStarLeagueYear())));
return panel;
}
@@ -1009,60 +1006,59 @@ private JPanel createPersonnelPanel() {
getChkGenerateCaptains().setName("chkGenerateCaptains");
setChkAssignCompanyCommanderFlag(new JCheckBox(resources.getString("chkAssignCompanyCommanderFlag.text")));
- getChkAssignCompanyCommanderFlag()
- .setToolTipText(resources.getString("chkAssignCompanyCommanderFlag.toolTipText"));
+ getChkAssignCompanyCommanderFlag().setToolTipText(resources.getString(
+ "chkAssignCompanyCommanderFlag.toolTipText"));
getChkAssignCompanyCommanderFlag().setName("chkAssignCompanyCommanderFlag");
- setChkApplyOfficerStatBonusToWorstSkill(
- new JCheckBox(resources.getString("chkApplyOfficerStatBonusToWorstSkill.text")));
- getChkApplyOfficerStatBonusToWorstSkill()
- .setToolTipText(resources.getString("chkApplyOfficerStatBonusToWorstSkill.toolTipText"));
+ setChkApplyOfficerStatBonusToWorstSkill(new JCheckBox(resources.getString(
+ "chkApplyOfficerStatBonusToWorstSkill.text")));
+ getChkApplyOfficerStatBonusToWorstSkill().setToolTipText(resources.getString(
+ "chkApplyOfficerStatBonusToWorstSkill.toolTipText"));
getChkApplyOfficerStatBonusToWorstSkill().setName("chkApplyOfficerStatBonusToWorstSkill");
setChkAssignBestCompanyCommander(new JCheckBox(resources.getString("chkAssignBestCompanyCommander.text")));
- getChkAssignBestCompanyCommander()
- .setToolTipText(resources.getString("chkAssignBestCompanyCommander.toolTipText"));
+ getChkAssignBestCompanyCommander().setToolTipText(resources.getString(
+ "chkAssignBestCompanyCommander.toolTipText"));
getChkAssignBestCompanyCommander().setName("chkAssignBestCompanyCommander");
- getChkAssignBestCompanyCommander().addActionListener(evt -> getChkPrioritizeCompanyCommanderCombatSkills()
- .setEnabled(getChkAssignBestCompanyCommander().isSelected()));
+ getChkAssignBestCompanyCommander().addActionListener(evt -> getChkPrioritizeCompanyCommanderCombatSkills().setEnabled(
+ getChkAssignBestCompanyCommander().isSelected()));
- setChkPrioritizeCompanyCommanderCombatSkills(
- new JCheckBox(resources.getString("chkPrioritizeCompanyCommanderCombatSkills.text")));
- getChkPrioritizeCompanyCommanderCombatSkills()
- .setToolTipText(resources.getString("chkPrioritizeCompanyCommanderCombatSkills.toolTipText"));
+ setChkPrioritizeCompanyCommanderCombatSkills(new JCheckBox(resources.getString(
+ "chkPrioritizeCompanyCommanderCombatSkills.text")));
+ getChkPrioritizeCompanyCommanderCombatSkills().setToolTipText(resources.getString(
+ "chkPrioritizeCompanyCommanderCombatSkills.toolTipText"));
getChkPrioritizeCompanyCommanderCombatSkills().setName("chkPrioritizeCompanyCommanderCombatSkills");
setChkAssignBestOfficers(new JCheckBox(resources.getString("chkAssignBestOfficers.text")));
getChkAssignBestOfficers().setToolTipText(resources.getString("chkAssignBestOfficers.toolTipText"));
getChkAssignBestOfficers().setName("chkAssignBestOfficers");
- getChkAssignBestOfficers().addActionListener(
- evt -> getChkPrioritizeOfficerCombatSkills().setEnabled(getChkAssignBestOfficers().isSelected()));
+ getChkAssignBestOfficers().addActionListener(evt -> getChkPrioritizeOfficerCombatSkills().setEnabled(
+ getChkAssignBestOfficers().isSelected()));
- setChkPrioritizeOfficerCombatSkills(
- new JCheckBox(resources.getString("chkPrioritizeOfficerCombatSkills.text")));
- getChkPrioritizeOfficerCombatSkills()
- .setToolTipText(resources.getString("chkPrioritizeOfficerCombatSkills.toolTipText"));
+ setChkPrioritizeOfficerCombatSkills(new JCheckBox(resources.getString("chkPrioritizeOfficerCombatSkills.text")));
+ getChkPrioritizeOfficerCombatSkills().setToolTipText(resources.getString(
+ "chkPrioritizeOfficerCombatSkills.toolTipText"));
getChkPrioritizeOfficerCombatSkills().setName("chkPrioritizeOfficerCombatSkills");
- setChkAssignMostSkilledToPrimaryLances(
- new JCheckBox(resources.getString("chkAssignMostSkilledToPrimaryLances.text")));
- getChkAssignMostSkilledToPrimaryLances()
- .setToolTipText(resources.getString("chkAssignMostSkilledToPrimaryLances.toolTipText"));
+ setChkAssignMostSkilledToPrimaryLances(new JCheckBox(resources.getString(
+ "chkAssignMostSkilledToPrimaryLances.text")));
+ getChkAssignMostSkilledToPrimaryLances().setToolTipText(resources.getString(
+ "chkAssignMostSkilledToPrimaryLances.toolTipText"));
getChkAssignMostSkilledToPrimaryLances().setName("chkAssignMostSkilledToPrimaryLances");
setChkAutomaticallyAssignRanks(new JCheckBox(resources.getString("chkAutomaticallyAssignRanks.text")));
getChkAutomaticallyAssignRanks().setToolTipText(resources.getString("chkAutomaticallyAssignRanks.toolTipText"));
getChkAutomaticallyAssignRanks().setName("chkAutomaticallyAssignRanks");
- setChkUseSpecifiedFactionToAssignRanks(
- new JCheckBox(resources.getString("chkUseSpecifiedFactionToAssignRanks.text")));
- getChkUseSpecifiedFactionToAssignRanks()
- .setToolTipText(resources.getString("chkUseSpecifiedFactionToAssignRanks.toolTipText"));
+ setChkUseSpecifiedFactionToAssignRanks(new JCheckBox(resources.getString(
+ "chkUseSpecifiedFactionToAssignRanks.text")));
+ getChkUseSpecifiedFactionToAssignRanks().setToolTipText(resources.getString(
+ "chkUseSpecifiedFactionToAssignRanks.toolTipText"));
getChkUseSpecifiedFactionToAssignRanks().setName("chkUseSpecifiedFactionToAssignRanks");
setChkAssignMekWarriorsCallsigns(new JCheckBox(resources.getString("chkAssignMekWarriorsCallsigns.text")));
- getChkAssignMekWarriorsCallsigns()
- .setToolTipText(resources.getString("chkAssignMekWarriorsCallsigns.toolTipText"));
+ getChkAssignMekWarriorsCallsigns().setToolTipText(resources.getString(
+ "chkAssignMekWarriorsCallsigns.toolTipText"));
getChkAssignMekWarriorsCallsigns().setName("chkAssignMekWarriorsCallsigns");
setChkAssignFounderFlag(new JCheckBox(resources.getString("chkAssignFounderFlag.text")));
@@ -1085,58 +1081,57 @@ private JPanel createPersonnelPanel() {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(getLblTotalSupportPersonnel())
- .addComponent(supportPersonnelNumbersPanel)
- .addComponent(getChkPoolAssistants())
- .addComponent(getChkGenerateCaptains())
- .addComponent(getChkAssignCompanyCommanderFlag())
- .addComponent(getChkApplyOfficerStatBonusToWorstSkill())
- .addComponent(getChkAssignBestCompanyCommander())
- .addComponent(getChkPrioritizeCompanyCommanderCombatSkills())
- .addComponent(getChkAssignBestOfficers())
- .addComponent(getChkPrioritizeOfficerCombatSkills())
- .addComponent(getChkAssignMostSkilledToPrimaryLances())
- .addComponent(getChkAutomaticallyAssignRanks())
- .addComponent(getChkUseSpecifiedFactionToAssignRanks())
- .addComponent(getChkAssignMekWarriorsCallsigns())
- .addComponent(getChkAssignFounderFlag()));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(getLblTotalSupportPersonnel())
- .addComponent(supportPersonnelNumbersPanel)
- .addComponent(getChkPoolAssistants())
- .addComponent(getChkGenerateCaptains())
- .addComponent(getChkAssignCompanyCommanderFlag())
- .addComponent(getChkApplyOfficerStatBonusToWorstSkill())
- .addComponent(getChkAssignBestCompanyCommander())
- .addComponent(getChkPrioritizeCompanyCommanderCombatSkills())
- .addComponent(getChkAssignBestOfficers())
- .addComponent(getChkPrioritizeOfficerCombatSkills())
- .addComponent(getChkAssignMostSkilledToPrimaryLances())
- .addComponent(getChkAutomaticallyAssignRanks())
- .addComponent(getChkUseSpecifiedFactionToAssignRanks())
- .addComponent(getChkAssignMekWarriorsCallsigns())
- .addComponent(getChkAssignFounderFlag()));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(getLblTotalSupportPersonnel())
+ .addComponent(supportPersonnelNumbersPanel)
+ .addComponent(getChkPoolAssistants())
+ .addComponent(getChkGenerateCaptains())
+ .addComponent(getChkAssignCompanyCommanderFlag())
+ .addComponent(getChkApplyOfficerStatBonusToWorstSkill())
+ .addComponent(getChkAssignBestCompanyCommander())
+ .addComponent(getChkPrioritizeCompanyCommanderCombatSkills())
+ .addComponent(getChkAssignBestOfficers())
+ .addComponent(getChkPrioritizeOfficerCombatSkills())
+ .addComponent(getChkAssignMostSkilledToPrimaryLances())
+ .addComponent(getChkAutomaticallyAssignRanks())
+ .addComponent(getChkUseSpecifiedFactionToAssignRanks())
+ .addComponent(getChkAssignMekWarriorsCallsigns())
+ .addComponent(getChkAssignFounderFlag()));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(getLblTotalSupportPersonnel())
+ .addComponent(supportPersonnelNumbersPanel)
+ .addComponent(getChkPoolAssistants())
+ .addComponent(getChkGenerateCaptains())
+ .addComponent(getChkAssignCompanyCommanderFlag())
+ .addComponent(getChkApplyOfficerStatBonusToWorstSkill())
+ .addComponent(getChkAssignBestCompanyCommander())
+ .addComponent(getChkPrioritizeCompanyCommanderCombatSkills())
+ .addComponent(getChkAssignBestOfficers())
+ .addComponent(getChkPrioritizeOfficerCombatSkills())
+ .addComponent(getChkAssignMostSkilledToPrimaryLances())
+ .addComponent(getChkAutomaticallyAssignRanks())
+ .addComponent(getChkUseSpecifiedFactionToAssignRanks())
+ .addComponent(getChkAssignMekWarriorsCallsigns())
+ .addComponent(getChkAssignFounderFlag()));
return panel;
}
private JPanel createSupportPersonnelNumbersPanel() {
- final PersonnelRole[] personnelRoles = new PersonnelRole[] {
- PersonnelRole.MEK_TECH, PersonnelRole.MECHANIC, PersonnelRole.AERO_TEK,
- PersonnelRole.BA_TECH, PersonnelRole.DOCTOR, PersonnelRole.ADMINISTRATOR_COMMAND,
- PersonnelRole.ADMINISTRATOR_LOGISTICS, PersonnelRole.ADMINISTRATOR_TRANSPORT,
- PersonnelRole.ADMINISTRATOR_HR
- };
+ final PersonnelRole[] personnelRoles = new PersonnelRole[] { PersonnelRole.MEK_TECH, PersonnelRole.MECHANIC,
+ PersonnelRole.AERO_TEK, PersonnelRole.BA_TECH,
+ PersonnelRole.DOCTOR,
+ PersonnelRole.ADMINISTRATOR_COMMAND,
+ PersonnelRole.ADMINISTRATOR_LOGISTICS,
+ PersonnelRole.ADMINISTRATOR_TRANSPORT,
+ PersonnelRole.ADMINISTRATOR_HR };
// Create Panel Components
setSpnSupportPersonnelNumbers(new HashMap<>());
final Map labels = new HashMap<>();
for (final PersonnelRole role : personnelRoles) {
- final String name = role.getName(getCampaign().getFaction().isClan());
+ final String name = role.getLabel(getCampaign().getFaction().isClan());
final String toolTipText = String.format(resources.getString("supportPersonnelNumber.toolTipText"), name);
labels.put(role, new JLabel(name));
@@ -1172,8 +1167,9 @@ private JPanel createSupportPersonnelNumbersPanel() {
}
private JPanel createPersonnelRandomizationPanel() {
- setRandomOriginOptionsPanel(new RandomOriginOptionsPanel(getFrame(), getCampaign(),
- getCampaign().getFaction()));
+ setRandomOriginOptionsPanel(new RandomOriginOptionsPanel(getFrame(),
+ getCampaign(),
+ getCampaign().getFaction()));
return getRandomOriginOptionsPanel();
}
@@ -1206,8 +1202,7 @@ private JPanel createStartingSimulationPanel() {
getChkSimulateRandomMarriages().setName("chkSimulateRandomMarriages");
setChkSimulateRandomProcreation(new JCheckBox(resources.getString("chkSimulateRandomProcreation.text")));
- getChkSimulateRandomProcreation()
- .setToolTipText(resources.getString("chkSimulateRandomProcreation.toolTipText"));
+ getChkSimulateRandomProcreation().setToolTipText(resources.getString("chkSimulateRandomProcreation.toolTipText"));
getChkSimulateRandomProcreation().setName("chkSimulateRandomProcreation");
// Programmatically Assign Accessibility Labels
@@ -1227,44 +1222,41 @@ private JPanel createStartingSimulationPanel() {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(getChkRunStartingSimulation())
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblSimulationDuration)
- .addComponent(getSpnSimulationDuration(), Alignment.LEADING))
- .addComponent(getChkSimulateRandomMarriages())
- .addComponent(getChkSimulateRandomProcreation()));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(getChkRunStartingSimulation())
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblSimulationDuration)
- .addComponent(getSpnSimulationDuration()))
- .addComponent(getChkSimulateRandomMarriages())
- .addComponent(getChkSimulateRandomProcreation()));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(getChkRunStartingSimulation())
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblSimulationDuration)
+ .addComponent(getSpnSimulationDuration(), Alignment.LEADING))
+ .addComponent(getChkSimulateRandomMarriages())
+ .addComponent(getChkSimulateRandomProcreation()));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(getChkRunStartingSimulation())
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblSimulationDuration)
+ .addComponent(getSpnSimulationDuration()))
+ .addComponent(getChkSimulateRandomMarriages())
+ .addComponent(getChkSimulateRandomProcreation()));
return panel;
}
private JPanel createUnitsPanel() {
// Create Panel Components
- final JLabel lblBattleMekFactionGenerationMethod = new JLabel(
- resources.getString("lblBattleMekFactionGenerationMethod.text"));
- lblBattleMekFactionGenerationMethod
- .setToolTipText(resources.getString("lblBattleMekFactionGenerationMethod.toolTipText"));
+ final JLabel lblBattleMekFactionGenerationMethod = new JLabel(resources.getString(
+ "lblBattleMekFactionGenerationMethod.text"));
+ lblBattleMekFactionGenerationMethod.setToolTipText(resources.getString(
+ "lblBattleMekFactionGenerationMethod.toolTipText"));
lblBattleMekFactionGenerationMethod.setName("lblBattleMekFactionGenerationMethod");
- setComboBattleMekFactionGenerationMethod(
- new MMComboBox<>("comboBattleMekFactionGenerationMethod", BattleMekFactionGenerationMethod.values()));
- getComboBattleMekFactionGenerationMethod()
- .setToolTipText(resources.getString("lblBattleMekFactionGenerationMethod.toolTipText"));
+ setComboBattleMekFactionGenerationMethod(new MMComboBox<>("comboBattleMekFactionGenerationMethod",
+ BattleMekFactionGenerationMethod.values()));
+ getComboBattleMekFactionGenerationMethod().setToolTipText(resources.getString(
+ "lblBattleMekFactionGenerationMethod.toolTipText"));
getComboBattleMekFactionGenerationMethod().setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(final JList> list, final Object value,
- final int index, final boolean isSelected,
- final boolean cellHasFocus) {
+ public Component getListCellRendererComponent(final JList> list, final Object value, final int index,
+ final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof BattleMekFactionGenerationMethod) {
list.setToolTipText(((BattleMekFactionGenerationMethod) value).getToolTipText());
@@ -1273,21 +1265,20 @@ public Component getListCellRendererComponent(final JList> list, final Object
}
});
- final JLabel lblBattleMekWeightClassGenerationMethod = new JLabel(
- resources.getString("lblBattleMekWeightClassGenerationMethod.text"));
- lblBattleMekWeightClassGenerationMethod
- .setToolTipText(resources.getString("lblBattleMekWeightClassGenerationMethod.toolTipText"));
+ final JLabel lblBattleMekWeightClassGenerationMethod = new JLabel(resources.getString(
+ "lblBattleMekWeightClassGenerationMethod.text"));
+ lblBattleMekWeightClassGenerationMethod.setToolTipText(resources.getString(
+ "lblBattleMekWeightClassGenerationMethod.toolTipText"));
lblBattleMekWeightClassGenerationMethod.setName("lblBattleMekWeightClassGenerationMethod");
setComboBattleMekWeightClassGenerationMethod(new MMComboBox<>("comboBattleMekWeightClassGenerationMethod",
- BattleMekWeightClassGenerationMethod.values()));
- getComboBattleMekWeightClassGenerationMethod()
- .setToolTipText(resources.getString("lblBattleMekWeightClassGenerationMethod.toolTipText"));
+ BattleMekWeightClassGenerationMethod.values()));
+ getComboBattleMekWeightClassGenerationMethod().setToolTipText(resources.getString(
+ "lblBattleMekWeightClassGenerationMethod.toolTipText"));
getComboBattleMekWeightClassGenerationMethod().setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(final JList> list, final Object value,
- final int index, final boolean isSelected,
- final boolean cellHasFocus) {
+ public Component getListCellRendererComponent(final JList> list, final Object value, final int index,
+ final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof BattleMekWeightClassGenerationMethod) {
list.setToolTipText(((BattleMekWeightClassGenerationMethod) value).getToolTipText());
@@ -1296,21 +1287,20 @@ public Component getListCellRendererComponent(final JList> list, final Object
}
});
- final JLabel lblBattleMekQualityGenerationMethod = new JLabel(
- resources.getString("lblBattleMekQualityGenerationMethod.text"));
- lblBattleMekQualityGenerationMethod
- .setToolTipText(resources.getString("lblBattleMekQualityGenerationMethod.toolTipText"));
+ final JLabel lblBattleMekQualityGenerationMethod = new JLabel(resources.getString(
+ "lblBattleMekQualityGenerationMethod.text"));
+ lblBattleMekQualityGenerationMethod.setToolTipText(resources.getString(
+ "lblBattleMekQualityGenerationMethod.toolTipText"));
lblBattleMekQualityGenerationMethod.setName("lblBattleMekQualityGenerationMethod");
- setComboBattleMekQualityGenerationMethod(
- new MMComboBox<>("comboBattleMekQualityGenerationMethod", BattleMekQualityGenerationMethod.values()));
- getComboBattleMekQualityGenerationMethod()
- .setToolTipText(resources.getString("lblBattleMekQualityGenerationMethod.toolTipText"));
+ setComboBattleMekQualityGenerationMethod(new MMComboBox<>("comboBattleMekQualityGenerationMethod",
+ BattleMekQualityGenerationMethod.values()));
+ getComboBattleMekQualityGenerationMethod().setToolTipText(resources.getString(
+ "lblBattleMekQualityGenerationMethod.toolTipText"));
getComboBattleMekQualityGenerationMethod().setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(final JList> list, final Object value,
- final int index, final boolean isSelected,
- final boolean cellHasFocus) {
+ public Component getListCellRendererComponent(final JList> list, final Object value, final int index,
+ final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof BattleMekQualityGenerationMethod) {
list.setToolTipText(((BattleMekQualityGenerationMethod) value).getToolTipText());
@@ -1320,18 +1310,16 @@ public Component getListCellRendererComponent(final JList> list, final Object
});
setChkNeverGenerateStarLeagueMeks(new JCheckBox(resources.getString("chkNeverGenerateStarLeagueMeks.text")));
- getChkNeverGenerateStarLeagueMeks()
- .setToolTipText(resources.getString("chkNeverGenerateStarLeagueMeks.toolTipText"));
+ getChkNeverGenerateStarLeagueMeks().setToolTipText(resources.getString(
+ "chkNeverGenerateStarLeagueMeks.toolTipText"));
getChkNeverGenerateStarLeagueMeks().setName("chkNeverGenerateStarLeagueMeks");
- getChkNeverGenerateStarLeagueMeks().addActionListener(evt -> getChkOnlyGenerateStarLeagueMeks()
- .setEnabled(!getChkNeverGenerateStarLeagueMeks().isSelected()));
+ getChkNeverGenerateStarLeagueMeks().addActionListener(evt -> getChkOnlyGenerateStarLeagueMeks().setEnabled(!getChkNeverGenerateStarLeagueMeks().isSelected()));
setChkOnlyGenerateStarLeagueMeks(new JCheckBox(resources.getString("chkOnlyGenerateStarLeagueMeks.text")));
- getChkOnlyGenerateStarLeagueMeks()
- .setToolTipText(resources.getString("chkOnlyGenerateStarLeagueMeks.toolTipText"));
+ getChkOnlyGenerateStarLeagueMeks().setToolTipText(resources.getString(
+ "chkOnlyGenerateStarLeagueMeks.toolTipText"));
getChkOnlyGenerateStarLeagueMeks().setName("chkOnlyGenerateStarLeagueMeks");
- getChkOnlyGenerateStarLeagueMeks().addActionListener(evt -> getChkNeverGenerateStarLeagueMeks()
- .setEnabled(!getChkOnlyGenerateStarLeagueMeks().isSelected()));
+ getChkOnlyGenerateStarLeagueMeks().addActionListener(evt -> getChkNeverGenerateStarLeagueMeks().setEnabled(!getChkOnlyGenerateStarLeagueMeks().isSelected()));
setChkOnlyGenerateOmniMeks(new JCheckBox(resources.getString("chkOnlyGenerateOmniMeks.text")));
getChkOnlyGenerateOmniMeks().setToolTipText(resources.getString("chkOnlyGenerateOmniMeks.toolTipText"));
@@ -1341,10 +1329,10 @@ public Component getListCellRendererComponent(final JList> list, final Object
getChkGenerateUnitsAsAttached().setToolTipText(resources.getString("chkGenerateUnitsAsAttached.toolTipText"));
getChkGenerateUnitsAsAttached().setName("chkGenerateUnitsAsAttached");
- setChkAssignBestRollToCompanyCommander(
- new JCheckBox(resources.getString("chkAssignBestRollToCompanyCommander.text")));
- getChkAssignBestRollToCompanyCommander()
- .setToolTipText(resources.getString("chkAssignBestRollToCompanyCommander.toolTipText"));
+ setChkAssignBestRollToCompanyCommander(new JCheckBox(resources.getString(
+ "chkAssignBestRollToCompanyCommander.text")));
+ getChkAssignBestRollToCompanyCommander().setToolTipText(resources.getString(
+ "chkAssignBestRollToCompanyCommander.toolTipText"));
getChkAssignBestRollToCompanyCommander().setName("chkAssignBestRollToCompanyCommander");
setChkSortStarLeagueUnitsFirst(new JCheckBox(resources.getString("chkSortStarLeagueUnitsFirst.text")));
@@ -1382,49 +1370,50 @@ public Component getListCellRendererComponent(final JList> list, final Object
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblBattleMekFactionGenerationMethod)
- .addComponent(getComboBattleMekFactionGenerationMethod(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblBattleMekWeightClassGenerationMethod)
- .addComponent(getComboBattleMekWeightClassGenerationMethod(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblBattleMekQualityGenerationMethod)
- .addComponent(getComboBattleMekQualityGenerationMethod(), Alignment.LEADING))
- .addComponent(getChkNeverGenerateStarLeagueMeks())
- .addComponent(getChkOnlyGenerateStarLeagueMeks())
- .addComponent(getChkOnlyGenerateOmniMeks())
- .addComponent(getChkGenerateUnitsAsAttached())
- .addComponent(getChkAssignBestRollToCompanyCommander())
- .addComponent(getChkSortStarLeagueUnitsFirst())
- .addComponent(getChkGroupByWeight())
- .addComponent(getChkGroupByQuality())
- .addComponent(getChkKeepOfficerRollsSeparate())
- .addComponent(getChkAssignTechsToUnits()));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblBattleMekFactionGenerationMethod)
- .addComponent(getComboBattleMekFactionGenerationMethod()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblBattleMekWeightClassGenerationMethod)
- .addComponent(getComboBattleMekWeightClassGenerationMethod()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblBattleMekQualityGenerationMethod)
- .addComponent(getComboBattleMekQualityGenerationMethod()))
- .addComponent(getChkNeverGenerateStarLeagueMeks())
- .addComponent(getChkOnlyGenerateStarLeagueMeks())
- .addComponent(getChkOnlyGenerateOmniMeks())
- .addComponent(getChkGenerateUnitsAsAttached())
- .addComponent(getChkAssignBestRollToCompanyCommander())
- .addComponent(getChkSortStarLeagueUnitsFirst())
- .addComponent(getChkGroupByWeight())
- .addComponent(getChkGroupByQuality())
- .addComponent(getChkKeepOfficerRollsSeparate())
- .addComponent(getChkAssignTechsToUnits()));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblBattleMekFactionGenerationMethod)
+ .addComponent(getComboBattleMekFactionGenerationMethod(),
+ Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblBattleMekWeightClassGenerationMethod)
+ .addComponent(getComboBattleMekWeightClassGenerationMethod(),
+ Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblBattleMekQualityGenerationMethod)
+ .addComponent(getComboBattleMekQualityGenerationMethod(),
+ Alignment.LEADING))
+ .addComponent(getChkNeverGenerateStarLeagueMeks())
+ .addComponent(getChkOnlyGenerateStarLeagueMeks())
+ .addComponent(getChkOnlyGenerateOmniMeks())
+ .addComponent(getChkGenerateUnitsAsAttached())
+ .addComponent(getChkAssignBestRollToCompanyCommander())
+ .addComponent(getChkSortStarLeagueUnitsFirst())
+ .addComponent(getChkGroupByWeight())
+ .addComponent(getChkGroupByQuality())
+ .addComponent(getChkKeepOfficerRollsSeparate())
+ .addComponent(getChkAssignTechsToUnits()));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblBattleMekFactionGenerationMethod)
+ .addComponent(getComboBattleMekFactionGenerationMethod()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblBattleMekWeightClassGenerationMethod)
+ .addComponent(getComboBattleMekWeightClassGenerationMethod()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblBattleMekQualityGenerationMethod)
+ .addComponent(getComboBattleMekQualityGenerationMethod()))
+ .addComponent(getChkNeverGenerateStarLeagueMeks())
+ .addComponent(getChkOnlyGenerateStarLeagueMeks())
+ .addComponent(getChkOnlyGenerateOmniMeks())
+ .addComponent(getChkGenerateUnitsAsAttached())
+ .addComponent(getChkAssignBestRollToCompanyCommander())
+ .addComponent(getChkSortStarLeagueUnitsFirst())
+ .addComponent(getChkGroupByWeight())
+ .addComponent(getChkGroupByQuality())
+ .addComponent(getChkKeepOfficerRollsSeparate())
+ .addComponent(getChkAssignTechsToUnits()));
return panel;
}
@@ -1442,9 +1431,8 @@ private JPanel createUnitPanel() {
getComboForceNamingMethod().setToolTipText(resources.getString("lblForceNamingMethod.toolTipText"));
getComboForceNamingMethod().setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(final JList> list, final Object value,
- final int index, final boolean isSelected,
- final boolean cellHasFocus) {
+ public Component getListCellRendererComponent(final JList> list, final Object value, final int index,
+ final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof ForceNamingMethod) {
list.setToolTipText(((ForceNamingMethod) value).getToolTipText());
@@ -1460,28 +1448,26 @@ public Component getListCellRendererComponent(final JList> list, final Object
final boolean selected = getChkGenerateForceIcons().isSelected();
getChkUseSpecifiedFactionToGenerateForceIcons().setEnabled(selected);
getChkGenerateOriginNodeForceIcon().setEnabled(selected);
- getChkUseOriginNodeForceIconLogo().setEnabled(selected
- && getChkGenerateOriginNodeForceIcon().isSelected());
+ getChkUseOriginNodeForceIconLogo().setEnabled(selected && getChkGenerateOriginNodeForceIcon().isSelected());
forceWeightLimitsPanel.setEnabled(selected);
});
- setChkUseSpecifiedFactionToGenerateForceIcons(
- new JCheckBox(resources.getString("chkUseSpecifiedFactionToGenerateForceIcons.text")));
- getChkUseSpecifiedFactionToGenerateForceIcons()
- .setToolTipText(resources.getString("chkUseSpecifiedFactionToGenerateForceIcons.toolTipText"));
+ setChkUseSpecifiedFactionToGenerateForceIcons(new JCheckBox(resources.getString(
+ "chkUseSpecifiedFactionToGenerateForceIcons.text")));
+ getChkUseSpecifiedFactionToGenerateForceIcons().setToolTipText(resources.getString(
+ "chkUseSpecifiedFactionToGenerateForceIcons.toolTipText"));
getChkUseSpecifiedFactionToGenerateForceIcons().setName("chkUseSpecifiedFactionToGenerateForceIcons");
setChkGenerateOriginNodeForceIcon(new JCheckBox(resources.getString("chkGenerateOriginNodeForceIcon.text")));
- getChkGenerateOriginNodeForceIcon()
- .setToolTipText(resources.getString("chkGenerateOriginNodeForceIcon.toolTipText"));
+ getChkGenerateOriginNodeForceIcon().setToolTipText(resources.getString(
+ "chkGenerateOriginNodeForceIcon.toolTipText"));
getChkGenerateOriginNodeForceIcon().setName("chkGenerateOriginNodeForceIcon");
- getChkGenerateOriginNodeForceIcon().addActionListener(evt -> getChkUseOriginNodeForceIconLogo()
- .setEnabled(getChkGenerateOriginNodeForceIcon().isEnabled()
- && getChkGenerateOriginNodeForceIcon().isSelected()));
+ getChkGenerateOriginNodeForceIcon().addActionListener(evt -> getChkUseOriginNodeForceIconLogo().setEnabled(
+ getChkGenerateOriginNodeForceIcon().isEnabled() && getChkGenerateOriginNodeForceIcon().isSelected()));
setChkUseOriginNodeForceIconLogo(new JCheckBox(resources.getString("chkUseOriginNodeForceIconLogo.text")));
- getChkUseOriginNodeForceIconLogo()
- .setToolTipText(resources.getString("chkUseOriginNodeForceIconLogo.toolTipText"));
+ getChkUseOriginNodeForceIconLogo().setToolTipText(resources.getString(
+ "chkUseOriginNodeForceIconLogo.toolTipText"));
getChkUseOriginNodeForceIconLogo().setName("chkUseOriginNodeForceIconLogo");
createForceWeightLimitsPanel(forceWeightLimitsPanel);
@@ -1499,27 +1485,25 @@ public Component getListCellRendererComponent(final JList> list, final Object
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblForceNamingMethod)
- .addComponent(getComboForceNamingMethod(), Alignment.LEADING))
- .addComponent(getChkGenerateForceIcons())
- .addComponent(getChkUseSpecifiedFactionToGenerateForceIcons())
- .addComponent(getChkGenerateOriginNodeForceIcon())
- .addComponent(getChkUseOriginNodeForceIconLogo())
- .addComponent(forceWeightLimitsPanel));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblForceNamingMethod)
- .addComponent(getComboForceNamingMethod()))
- .addComponent(getChkGenerateForceIcons())
- .addComponent(getChkUseSpecifiedFactionToGenerateForceIcons())
- .addComponent(getChkGenerateOriginNodeForceIcon())
- .addComponent(getChkUseOriginNodeForceIconLogo())
- .addComponent(forceWeightLimitsPanel));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblForceNamingMethod)
+ .addComponent(getComboForceNamingMethod(), Alignment.LEADING))
+ .addComponent(getChkGenerateForceIcons())
+ .addComponent(getChkUseSpecifiedFactionToGenerateForceIcons())
+ .addComponent(getChkGenerateOriginNodeForceIcon())
+ .addComponent(getChkUseOriginNodeForceIconLogo())
+ .addComponent(forceWeightLimitsPanel));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblForceNamingMethod)
+ .addComponent(getComboForceNamingMethod()))
+ .addComponent(getChkGenerateForceIcons())
+ .addComponent(getChkUseSpecifiedFactionToGenerateForceIcons())
+ .addComponent(getChkGenerateOriginNodeForceIcon())
+ .addComponent(getChkUseOriginNodeForceIconLogo())
+ .addComponent(forceWeightLimitsPanel));
return panel;
}
@@ -1553,8 +1537,8 @@ private JPanel createSparesPanel() {
// Create Panel Components
setChkGenerateMothballedSpareUnits(new JCheckBox(resources.getString("chkGenerateMothballedSpareUnits.text")));
- getChkGenerateMothballedSpareUnits()
- .setToolTipText(resources.getString("chkGenerateMothballedSpareUnits.toolTipText"));
+ getChkGenerateMothballedSpareUnits().setToolTipText(resources.getString(
+ "chkGenerateMothballedSpareUnits.toolTipText"));
getChkGenerateMothballedSpareUnits().setName("chkGenerateMothballedSpareUnits");
getChkGenerateMothballedSpareUnits().addActionListener(evt -> {
final boolean selected = getChkGenerateMothballedSpareUnits().isSelected();
@@ -1567,8 +1551,8 @@ private JPanel createSparesPanel() {
lblSparesPercentOfActiveUnits.setName("lblSparesPercentOfActiveUnits");
setSpnSparesPercentOfActiveUnits(new JSpinner(new SpinnerNumberModel(0, 0, 100, 1)));
- getSpnSparesPercentOfActiveUnits()
- .setToolTipText(resources.getString("chkGenerateMothballedSpareUnits.toolTipText"));
+ getSpnSparesPercentOfActiveUnits().setToolTipText(resources.getString(
+ "chkGenerateMothballedSpareUnits.toolTipText"));
getSpnSparesPercentOfActiveUnits().setName("spnGenerateMothballedSpareUnits");
final JLabel lblPartGenerationMethod = new JLabel(resources.getString("lblPartGenerationMethod.text"));
@@ -1579,9 +1563,8 @@ private JPanel createSparesPanel() {
getComboPartGenerationMethod().setToolTipText(resources.getString("lblPartGenerationMethod.toolTipText"));
getComboPartGenerationMethod().setRenderer(new DefaultListCellRenderer() {
@Override
- public Component getListCellRendererComponent(final JList> list, final Object value,
- final int index, final boolean isSelected,
- final boolean cellHasFocus) {
+ public Component getListCellRendererComponent(final JList> list, final Object value, final int index,
+ final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof PartGenerationMethod) {
list.setToolTipText(((PartGenerationMethod) value).getToolTipText());
@@ -1616,10 +1599,10 @@ public Component getListCellRendererComponent(final JList> list, final Object
getSpnNumberReloadsPerWeapon().setToolTipText(resources.getString("lblNumberReloadsPerWeapon.toolTipText"));
getSpnNumberReloadsPerWeapon().setName("spnNumberReloadsPerWeapon");
- setChkGenerateFractionalMachineGunAmmunition(
- new JCheckBox(resources.getString("chkGenerateFractionalMachineGunAmmunition.text")));
- getChkGenerateFractionalMachineGunAmmunition()
- .setToolTipText(resources.getString("chkGenerateFractionalMachineGunAmmunition.toolTipText"));
+ setChkGenerateFractionalMachineGunAmmunition(new JCheckBox(resources.getString(
+ "chkGenerateFractionalMachineGunAmmunition.text")));
+ getChkGenerateFractionalMachineGunAmmunition().setToolTipText(resources.getString(
+ "chkGenerateFractionalMachineGunAmmunition.toolTipText"));
getChkGenerateFractionalMachineGunAmmunition().setName("chkGenerateFractionalMachineGunAmmunition");
// Programmatically Assign Accessibility Labels
@@ -1644,41 +1627,40 @@ public Component getListCellRendererComponent(final JList> list, final Object
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(getChkGenerateMothballedSpareUnits())
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblSparesPercentOfActiveUnits)
- .addComponent(getSpnSparesPercentOfActiveUnits(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblPartGenerationMethod)
- .addComponent(getComboPartGenerationMethod(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblStartingArmourWeight)
- .addComponent(getSpnStartingArmourWeight(), Alignment.LEADING))
- .addComponent(getChkGenerateSpareAmmunition())
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblNumberReloadsPerWeapon)
- .addComponent(getSpnNumberReloadsPerWeapon(), Alignment.LEADING))
- .addComponent(getChkGenerateFractionalMachineGunAmmunition()));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(getChkGenerateMothballedSpareUnits())
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblSparesPercentOfActiveUnits)
- .addComponent(getSpnSparesPercentOfActiveUnits()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblPartGenerationMethod)
- .addComponent(getComboPartGenerationMethod()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblStartingArmourWeight)
- .addComponent(getSpnStartingArmourWeight()))
- .addComponent(getChkGenerateSpareAmmunition())
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblNumberReloadsPerWeapon)
- .addComponent(getSpnNumberReloadsPerWeapon()))
- .addComponent(getChkGenerateFractionalMachineGunAmmunition()));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(getChkGenerateMothballedSpareUnits())
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblSparesPercentOfActiveUnits)
+ .addComponent(getSpnSparesPercentOfActiveUnits(),
+ Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblPartGenerationMethod)
+ .addComponent(getComboPartGenerationMethod(), Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblStartingArmourWeight)
+ .addComponent(getSpnStartingArmourWeight(), Alignment.LEADING))
+ .addComponent(getChkGenerateSpareAmmunition())
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblNumberReloadsPerWeapon)
+ .addComponent(getSpnNumberReloadsPerWeapon(), Alignment.LEADING))
+ .addComponent(getChkGenerateFractionalMachineGunAmmunition()));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(getChkGenerateMothballedSpareUnits())
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblSparesPercentOfActiveUnits)
+ .addComponent(getSpnSparesPercentOfActiveUnits()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblPartGenerationMethod)
+ .addComponent(getComboPartGenerationMethod()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblStartingArmourWeight)
+ .addComponent(getSpnStartingArmourWeight()))
+ .addComponent(getChkGenerateSpareAmmunition())
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblNumberReloadsPerWeapon)
+ .addComponent(getSpnNumberReloadsPerWeapon()))
+ .addComponent(getChkGenerateFractionalMachineGunAmmunition()));
return panel;
}
@@ -1697,8 +1679,8 @@ private JPanel createContractsPanel() {
});
setChkStartCourseToContractPlanet(new JCheckBox(resources.getString("chkStartCourseToContractPlanet.text")));
- getChkStartCourseToContractPlanet()
- .setToolTipText(resources.getString("chkStartCourseToContractPlanet.toolTipText"));
+ getChkStartCourseToContractPlanet().setToolTipText(resources.getString(
+ "chkStartCourseToContractPlanet.toolTipText"));
getChkStartCourseToContractPlanet().setName("chkStartCourseToContractPlanet");
// Disable Panel by Default
@@ -1715,15 +1697,13 @@ private JPanel createContractsPanel() {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(getChkSelectStartingContract())
- .addComponent(getChkStartCourseToContractPlanet()));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(getChkSelectStartingContract())
+ .addComponent(getChkStartCourseToContractPlanet()));
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(getChkSelectStartingContract())
- .addComponent(getChkStartCourseToContractPlanet()));
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(getChkSelectStartingContract())
+ .addComponent(getChkStartCourseToContractPlanet()));
// TODO : Wave 5 : Company Generation GUI
panel.setEnabled(false);
@@ -1776,17 +1756,15 @@ private JPanel createFinancesPanel() {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(getChkProcessFinances())
- .addComponent(financialCreditsPanel)
- .addComponent(financialDebitsPanel));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(getChkProcessFinances())
+ .addComponent(financialCreditsPanel)
+ .addComponent(financialDebitsPanel));
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(getChkProcessFinances())
- .addComponent(financialCreditsPanel)
- .addComponent(financialDebitsPanel));
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(getChkProcessFinances())
+ .addComponent(financialCreditsPanel)
+ .addComponent(financialDebitsPanel));
return panel;
}
@@ -1816,13 +1794,12 @@ private void createFinancialCreditsPanel(final JPanel panel) {
});
lblRandomStartingCashDiceCount.setText(resources.getString("lblRandomStartingCashDiceCount.text"));
- lblRandomStartingCashDiceCount
- .setToolTipText(resources.getString("lblRandomStartingCashDiceCount.toolTipText"));
+ lblRandomStartingCashDiceCount.setToolTipText(resources.getString("lblRandomStartingCashDiceCount.toolTipText"));
lblRandomStartingCashDiceCount.setName("lblRandomStartingCashDiceCount");
setSpnRandomStartingCashDiceCount(new JSpinner(new SpinnerNumberModel(8, 1, 100, 1)));
- getSpnRandomStartingCashDiceCount()
- .setToolTipText(resources.getString("lblRandomStartingCashDiceCount.toolTipText"));
+ getSpnRandomStartingCashDiceCount().setToolTipText(resources.getString(
+ "lblRandomStartingCashDiceCount.toolTipText"));
getSpnRandomStartingCashDiceCount().setName("spnRandomStartingCashDiceCount");
final JLabel lblMinimumStartingFloat = new JLabel(resources.getString("lblMinimumStartingFloat.text"));
@@ -1833,10 +1810,9 @@ private void createFinancialCreditsPanel(final JPanel panel) {
getSpnMinimumStartingFloat().setToolTipText(resources.getString("lblMinimumStartingFloat.toolTipText"));
getSpnMinimumStartingFloat().setName("spnMinimumStartingFloat");
- setChkIncludeInitialContractPayment(
- new JCheckBox(resources.getString("chkIncludeInitialContractPayment.text")));
- getChkIncludeInitialContractPayment()
- .setToolTipText(resources.getString("chkIncludeInitialContractPayment.toolTipText"));
+ setChkIncludeInitialContractPayment(new JCheckBox(resources.getString("chkIncludeInitialContractPayment.text")));
+ getChkIncludeInitialContractPayment().setToolTipText(resources.getString(
+ "chkIncludeInitialContractPayment.toolTipText"));
getChkIncludeInitialContractPayment().setName("chkIncludeInitialContractPayment");
setChkStartingLoan(new JCheckBox(resources.getString("chkStartingLoan.text")));
@@ -1859,35 +1835,34 @@ private void createFinancialCreditsPanel(final JPanel panel) {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblStartingCash)
- .addComponent(getSpnStartingCash(), Alignment.LEADING))
- .addComponent(getChkRandomizeStartingCash())
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblRandomStartingCashDiceCount)
- .addComponent(getSpnRandomStartingCashDiceCount(), Alignment.LEADING))
- .addGroup(layout.createParallelGroup(Alignment.BASELINE)
- .addComponent(lblMinimumStartingFloat)
- .addComponent(getSpnMinimumStartingFloat(), Alignment.LEADING))
- .addComponent(getChkIncludeInitialContractPayment())
- .addComponent(getChkStartingLoan()));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblStartingCash)
- .addComponent(getSpnStartingCash()))
- .addComponent(getChkRandomizeStartingCash())
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblRandomStartingCashDiceCount)
- .addComponent(getSpnRandomStartingCashDiceCount()))
- .addGroup(layout.createSequentialGroup()
- .addComponent(lblMinimumStartingFloat)
- .addComponent(getSpnMinimumStartingFloat()))
- .addComponent(getChkIncludeInitialContractPayment())
- .addComponent(getChkStartingLoan()));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblStartingCash)
+ .addComponent(getSpnStartingCash(), Alignment.LEADING))
+ .addComponent(getChkRandomizeStartingCash())
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblRandomStartingCashDiceCount)
+ .addComponent(getSpnRandomStartingCashDiceCount(),
+ Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblMinimumStartingFloat)
+ .addComponent(getSpnMinimumStartingFloat(), Alignment.LEADING))
+ .addComponent(getChkIncludeInitialContractPayment())
+ .addComponent(getChkStartingLoan()));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblStartingCash)
+ .addComponent(getSpnStartingCash()))
+ .addComponent(getChkRandomizeStartingCash())
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblRandomStartingCashDiceCount)
+ .addComponent(getSpnRandomStartingCashDiceCount()))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblMinimumStartingFloat)
+ .addComponent(getSpnMinimumStartingFloat()))
+ .addComponent(getChkIncludeInitialContractPayment())
+ .addComponent(getChkStartingLoan()));
}
private void createFinancialDebitsPanel(final JPanel panel) {
@@ -1935,23 +1910,21 @@ private void createFinancialDebitsPanel(final JPanel panel) {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(getChkPayForSetup())
- .addComponent(getChkPayForPersonnel())
- .addComponent(getChkPayForUnits())
- .addComponent(getChkPayForParts())
- .addComponent(getChkPayForArmour())
- .addComponent(getChkPayForAmmunition()));
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(getChkPayForSetup())
- .addComponent(getChkPayForPersonnel())
- .addComponent(getChkPayForUnits())
- .addComponent(getChkPayForParts())
- .addComponent(getChkPayForArmour())
- .addComponent(getChkPayForAmmunition()));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(getChkPayForSetup())
+ .addComponent(getChkPayForPersonnel())
+ .addComponent(getChkPayForUnits())
+ .addComponent(getChkPayForParts())
+ .addComponent(getChkPayForArmour())
+ .addComponent(getChkPayForAmmunition()));
+
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(getChkPayForSetup())
+ .addComponent(getChkPayForPersonnel())
+ .addComponent(getChkPayForUnits())
+ .addComponent(getChkPayForParts())
+ .addComponent(getChkPayForArmour())
+ .addComponent(getChkPayForAmmunition()));
}
private JPanel createSurprisesPanel() {
@@ -1971,8 +1944,7 @@ private JPanel createSurprisesPanel() {
setChkGenerateMysteryBoxes(new JCheckBox(resources.getString("chkGenerateMysteryBoxes.text")));
getChkGenerateMysteryBoxes().setToolTipText(resources.getString("chkGenerateMysteryBoxes.toolTipText"));
getChkGenerateMysteryBoxes().setName("chkGenerateMysteryBoxes");
- getChkGenerateMysteryBoxes().addActionListener(evt -> mysteryBoxPanel.setEnabled(
- getChkGenerateMysteryBoxes().isSelected()));
+ getChkGenerateMysteryBoxes().addActionListener(evt -> mysteryBoxPanel.setEnabled(getChkGenerateMysteryBoxes().isSelected()));
createMysteryBoxPanel(mysteryBoxPanel);
@@ -1991,17 +1963,15 @@ private JPanel createSurprisesPanel() {
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(getChkGenerateSurprises())
- .addComponent(getChkGenerateMysteryBoxes())
- .addComponent(mysteryBoxPanel));
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addComponent(getChkGenerateSurprises())
+ .addComponent(getChkGenerateMysteryBoxes())
+ .addComponent(mysteryBoxPanel));
- layout.setHorizontalGroup(
- layout.createParallelGroup(Alignment.LEADING)
- .addComponent(getChkGenerateSurprises())
- .addComponent(getChkGenerateMysteryBoxes())
- .addComponent(mysteryBoxPanel));
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(getChkGenerateSurprises())
+ .addComponent(getChkGenerateMysteryBoxes())
+ .addComponent(mysteryBoxPanel));
// TODO : Wave 7 : Surprises
panel.setEnabled(false);
@@ -2030,36 +2000,33 @@ private void createMysteryBoxPanel(final JPanel panel) {
// endregion Initialization
// region Options
+
/**
- * Sets the options for this panel to the default for the selected
- * CompanyGenerationMethod
+ * Sets the options for this panel to the default for the selected CompanyGenerationMethod
*/
public void setOptions() {
setOptions(getComboCompanyGenerationMethod().getSelectedItem());
}
/**
- * Sets the options for this panel to the default for the provided
- * CompanyGenerationMethod
+ * Sets the options for this panel to the default for the provided CompanyGenerationMethod
*
- * @param method the CompanyGenerationOptions to create the
- * CompanyGenerationOptions from
+ * @param method the CompanyGenerationOptions to create the CompanyGenerationOptions from
*/
public void setOptions(final CompanyGenerationMethod method) {
setOptions(new CompanyGenerationOptions(method));
}
/**
- * Sets the options for this panel based on the provided
- * CompanyGenerationOptions
+ * Sets the options for this panel based on the provided CompanyGenerationOptions
*
* @param options the CompanyGenerationOptions to use
*/
public void setOptions(final CompanyGenerationOptions options) {
// Base Information
getComboCompanyGenerationMethod().setSelectedItem(options.getMethod());
- getComboSpecifiedFaction()
- .setSelectedItem(new FactionDisplay(options.getSpecifiedFaction(), getCampaign().getLocalDate()));
+ getComboSpecifiedFaction().setSelectedItem(new FactionDisplay(options.getSpecifiedFaction(),
+ getCampaign().getLocalDate()));
getChkGenerateMercenaryCompanyCommandLance().setSelected(options.isGenerateMercenaryCompanyCommandLance());
getSpnCompanyCount().setValue(options.getCompanyCount());
getSpnIndividualLanceCount().setValue(options.getIndividualLanceCount());
@@ -2103,8 +2070,7 @@ public void setOptions(final CompanyGenerationOptions options) {
// Units
getComboBattleMekFactionGenerationMethod().setSelectedItem(options.getBattleMekFactionGenerationMethod());
- getComboBattleMekWeightClassGenerationMethod()
- .setSelectedItem(options.getBattleMekWeightClassGenerationMethod());
+ getComboBattleMekWeightClassGenerationMethod().setSelectedItem(options.getBattleMekWeightClassGenerationMethod());
getComboBattleMekQualityGenerationMethod().setSelectedItem(options.getBattleMekQualityGenerationMethod());
getChkNeverGenerateStarLeagueMeks().setSelected(options.isNeverGenerateStarLeagueMeks());
getChkOnlyGenerateStarLeagueMeks().setSelected(options.isOnlyGenerateStarLeagueMeks());
@@ -2122,8 +2088,7 @@ public void setOptions(final CompanyGenerationOptions options) {
if (getChkGenerateForceIcons().isSelected() != options.isGenerateForceIcons()) {
getChkGenerateForceIcons().doClick();
}
- getChkUseSpecifiedFactionToGenerateForceIcons()
- .setSelected(options.isUseSpecifiedFactionToGenerateForceIcons());
+ getChkUseSpecifiedFactionToGenerateForceIcons().setSelected(options.isUseSpecifiedFactionToGenerateForceIcons());
if (getChkGenerateOriginNodeForceIcon().isSelected() != options.isGenerateOriginNodeForceIcon()) {
getChkGenerateOriginNodeForceIcon().doClick();
}
@@ -2190,8 +2155,7 @@ public void setOptions(final CompanyGenerationOptions options) {
* @return the CompanyGenerationOptions created from the current panel
*/
public CompanyGenerationOptions createOptionsFromPanel() {
- final CompanyGenerationOptions options = new CompanyGenerationOptions(
- getComboCompanyGenerationMethod().getSelectedItem());
+ final CompanyGenerationOptions options = new CompanyGenerationOptions(getComboCompanyGenerationMethod().getSelectedItem());
// Base Information
options.setSpecifiedFaction(Objects.requireNonNull(getComboSpecifiedFaction().getSelectedItem()).getFaction());
@@ -2236,8 +2200,7 @@ public CompanyGenerationOptions createOptionsFromPanel() {
// Units
options.setBattleMekFactionGenerationMethod(getComboBattleMekFactionGenerationMethod().getSelectedItem());
- options.setBattleMekWeightClassGenerationMethod(
- getComboBattleMekWeightClassGenerationMethod().getSelectedItem());
+ options.setBattleMekWeightClassGenerationMethod(getComboBattleMekWeightClassGenerationMethod().getSelectedItem());
options.setBattleMekQualityGenerationMethod(getComboBattleMekQualityGenerationMethod().getSelectedItem());
options.setNeverGenerateStarLeagueMeks(getChkNeverGenerateStarLeagueMeks().isSelected());
options.setOnlyGenerateStarLeagueMeks(getChkOnlyGenerateStarLeagueMeks().isSelected());
@@ -2253,8 +2216,7 @@ public CompanyGenerationOptions createOptionsFromPanel() {
// Unit
options.setForceNamingMethod(getComboForceNamingMethod().getSelectedItem());
options.setGenerateForceIcons(getChkGenerateForceIcons().isSelected());
- options.setUseSpecifiedFactionToGenerateForceIcons(
- getChkUseSpecifiedFactionToGenerateForceIcons().isSelected());
+ options.setUseSpecifiedFactionToGenerateForceIcons(getChkUseSpecifiedFactionToGenerateForceIcons().isSelected());
options.setGenerateOriginNodeForceIcon(getChkGenerateOriginNodeForceIcon().isSelected());
options.setUseOriginNodeForceIconLogo(getChkUseOriginNodeForceIconLogo().isSelected());
options.setForceWeightLimits(new TreeMap<>());
@@ -2302,10 +2264,10 @@ public CompanyGenerationOptions createOptionsFromPanel() {
}
/**
- * Validates the data contained in this panel, returning the current state of
- * validation.
+ * Validates the data contained in this panel, returning the current state of validation.
*
* @param display to display dialogs containing the messages or not
+ *
* @return true if the data validates successfully, otherwise false
*/
public ValidationState validateOptions(final boolean display) {
@@ -2313,13 +2275,12 @@ public ValidationState validateOptions(final boolean display) {
// Minimum Generation Size Validation
// Minimum Generation Parameter of 1 Company or Lance, the Company Command Lance
// Doesn't Count
- if (((int) getSpnCompanyCount().getValue() <= 0)
- && ((int) getSpnIndividualLanceCount().getValue() <= 0)) {
+ if (((int) getSpnCompanyCount().getValue() <= 0) && ((int) getSpnIndividualLanceCount().getValue() <= 0)) {
if (display) {
JOptionPane.showMessageDialog(getFrame(),
- resources.getString("CompanyGenerationOptionsPanel.InvalidGenerationSize.text"),
- resources.getString("InvalidOptions.title"),
- JOptionPane.ERROR_MESSAGE);
+ resources.getString("CompanyGenerationOptionsPanel.InvalidGenerationSize.text"),
+ resources.getString("InvalidOptions.title"),
+ JOptionPane.ERROR_MESSAGE);
}
return ValidationState.FAILURE;
}
@@ -2365,12 +2326,13 @@ public ValidationState validateOptions(final boolean display) {
// endregion Options
// region File I/O
+
/**
* Imports CompanyGenerationOptions from an XML file
*/
public void importOptionsFromXML() {
FileDialogs.openCompanyGenerationOptions(getFrame())
- .ifPresent(file -> setOptions(CompanyGenerationOptions.parseFromXML(file)));
+ .ifPresent(file -> setOptions(CompanyGenerationOptions.parseFromXML(file)));
}
/**
@@ -2378,7 +2340,7 @@ public void importOptionsFromXML() {
*/
public void exportOptionsToXML() {
FileDialogs.saveCompanyGenerationOptions(getFrame())
- .ifPresent(file -> createOptionsFromPanel().writeToFile(file));
+ .ifPresent(file -> createOptionsFromPanel().writeToFile(file));
}
// endregion File I/O
}
diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelRoleTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelRoleTest.java
index 1b8efa8056a..ac6a94db096 100644
--- a/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelRoleTest.java
+++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelRoleTest.java
@@ -27,6 +27,8 @@
*/
package mekhq.campaign.personnel.enums;
+import static mekhq.campaign.personnel.enums.PersonnelRole.BATTLE_ARMOUR;
+import static mekhq.utilities.MHQInternationalization.isResourceKeyValid;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -35,31 +37,29 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
-import java.util.ResourceBundle;
import java.util.Set;
-import mekhq.MekHQ;
import org.junit.jupiter.api.Test;
class PersonnelRoleTest {
- // region Variable Declarations
private static final PersonnelRole[] roles = PersonnelRole.values();
- private final transient ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel",
- MekHQ.getMHQOptions().getLocale());
- // endregion Variable Declarations
+ @Test
+ void testGetLabel_NotClan() {
+ for (final PersonnelRole personnelRole : roles) {
+ String label = personnelRole.getLabel(false);
+ boolean isValid = isResourceKeyValid(label);
+ assertTrue(isValid, "Invalid resource key: " + label);
+ }
+ }
- // region Getters
@Test
- void testGetName() {
- assertEquals(resources.getString("PersonnelRole.MEKWARRIOR.text"), PersonnelRole.MEKWARRIOR.getName(false));
- assertEquals(resources.getString("PersonnelRole.MEKWARRIOR.text"), PersonnelRole.MEKWARRIOR.getName(true));
- assertEquals(resources.getString("PersonnelRole.BATTLE_ARMOUR.text"),
- PersonnelRole.BATTLE_ARMOUR.getName(false));
- assertEquals(resources.getString("PersonnelRole.BATTLE_ARMOUR.clan.text"),
- PersonnelRole.BATTLE_ARMOUR.getName(true));
- assertEquals(resources.getString("PersonnelRole.ADMINISTRATOR_LOGISTICS.text"),
- PersonnelRole.ADMINISTRATOR_LOGISTICS.getName(false));
+ void testGetLabel_IsClan() {
+ for (final PersonnelRole personnelRole : roles) {
+ String label = personnelRole.getLabel(true);
+ boolean isValid = isResourceKeyValid(label);
+ assertTrue(isValid, "Invalid resource key: " + label);
+ }
}
@Test
@@ -75,6 +75,7 @@ void testGetMnemonicEnsureUniqueness() {
usedMnemonics.add(role.getMnemonic());
}
}
+
// endregion Getters
// region Boolean Comparison Methods
@@ -191,7 +192,7 @@ void testIsProtoMekPilot() {
@Test
void testIsBattleArmour() {
for (final PersonnelRole personnelRole : roles) {
- if (personnelRole == PersonnelRole.BATTLE_ARMOUR) {
+ if (personnelRole == BATTLE_ARMOUR) {
assertTrue(personnelRole.isBattleArmour());
} else {
assertFalse(personnelRole.isBattleArmour());
@@ -519,7 +520,7 @@ void testIsVehicleCrewMember() {
@Test
void testIsSoldierOrBattleArmour() {
for (final PersonnelRole personnelRole : roles) {
- if ((personnelRole == PersonnelRole.SOLDIER) || (personnelRole == PersonnelRole.BATTLE_ARMOUR)) {
+ if ((personnelRole == PersonnelRole.SOLDIER) || (personnelRole == BATTLE_ARMOUR)) {
assertTrue(personnelRole.isSoldierOrBattleArmour());
} else {
assertFalse(personnelRole.isSoldierOrBattleArmour());
@@ -646,6 +647,34 @@ void testGetMarketableRoles() {
assertFalse(militaryRoles.contains(PersonnelRole.NONE));
}
+ @Test
+ void testFromString() {
+ // Valid inputs
+ assertEquals(PersonnelRole.MEKWARRIOR, PersonnelRole.fromString("MEKWARRIOR"));
+ assertEquals(PersonnelRole.GROUND_VEHICLE_DRIVER, PersonnelRole.fromString("GROUND_VEHICLE_DRIVER"));
+ assertEquals(PersonnelRole.ASTECH, PersonnelRole.fromString("ASTECH"));
+
+ // Valid inputs with variations in casing
+ assertEquals(PersonnelRole.MEKWARRIOR, PersonnelRole.fromString("MekWarrior"));
+ assertEquals(PersonnelRole.VEHICLE_CREW, PersonnelRole.fromString("vehicle_crew"));
+
+ // Valid inputs with Clan variance
+ assertEquals(BATTLE_ARMOUR, PersonnelRole.fromString("elemental"));
+ assertEquals(BATTLE_ARMOUR, PersonnelRole.fromString("Battle Armor Pilot"));
+
+ // Deprecated names
+ assertEquals(PersonnelRole.MEKWARRIOR, PersonnelRole.fromString("MechWarrior"));
+ assertEquals(PersonnelRole.PROTOMEK_PILOT, PersonnelRole.fromString("protomek PILOT"));
+
+ // Index input
+ assertEquals(BATTLE_ARMOUR, PersonnelRole.fromString(BATTLE_ARMOUR.ordinal() + ""));
+
+ // Invalid inputs
+ assertEquals(PersonnelRole.NONE, PersonnelRole.fromString("INVALID_ROLE"));
+ assertEquals(PersonnelRole.NONE, PersonnelRole.fromString(""));
+ assertEquals(PersonnelRole.NONE, PersonnelRole.fromString(null));
+ }
+
@Test
void testGetPrimaryRoles() {
// This should be all roles bar one, namely PersonnelRole.NONE
@@ -693,23 +722,5 @@ void testGetCivilianCount() {
// endregion Static Methods
// region File I/O
- @Test
- void testParseFromString() {
- // Normal Parsing
- assertEquals(PersonnelRole.NONE, PersonnelRole.parseFromString("NONE"));
- assertEquals(PersonnelRole.BATTLE_ARMOUR, PersonnelRole.parseFromString("BATTLE_ARMOUR"));
- assertEquals(PersonnelRole.ADMINISTRATOR_LOGISTICS, PersonnelRole.parseFromString("ADMINISTRATOR_LOGISTICS"));
-
- // Error Case
- assertEquals(PersonnelRole.NONE, PersonnelRole.parseFromString("28"));
- assertEquals(PersonnelRole.NONE, PersonnelRole.parseFromString("blah"));
- }
// endregion File I/O
-
- @Test
- void testToStringOverride() {
- assertEquals(resources.getString("PersonnelRole.MEKWARRIOR.text"), PersonnelRole.MEKWARRIOR.toString());
- assertEquals(resources.getString("PersonnelRole.ADMINISTRATOR_LOGISTICS.text"),
- PersonnelRole.ADMINISTRATOR_LOGISTICS.toString());
- }
}
From df96a91c9c977dcba6035361feb18f1fe5c9d2a4 Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Sun, 6 Apr 2025 17:56:48 -0500
Subject: [PATCH 06/10] - Introduced a command
(`CMD_GENERATE_ROLEPLAY_ATTRIBUTES`) to generate random roleplay attributes
for personnel.es.
---
.../resources/mekhq/resources/GUI.properties | 3 +-
.../personnel/enums/PersonnelRole.java | 62 +++++++++----------
.../generator/DefaultSkillGenerator.java | 6 +-
.../adapter/PersonnelTableMouseAdapter.java | 15 +++++
4 files changed, 49 insertions(+), 37 deletions(-)
diff --git a/MekHQ/resources/mekhq/resources/GUI.properties b/MekHQ/resources/mekhq/resources/GUI.properties
index daa9dde4489..9fac966fd81 100644
--- a/MekHQ/resources/mekhq/resources/GUI.properties
+++ b/MekHQ/resources/mekhq/resources/GUI.properties
@@ -281,7 +281,8 @@ removePregnancies.text=Remove Pregnancies
regenerateLoyalty.text=Regenerate Loyalty
regeneratePersonality.text=Regenerate Personality
addRandomSPA.text=Add Random SPA
-generateRoleplaySkills.text=Generate Roleplay Skills
+generateRoleplaySkills.text=Generate Random Roleplay Skills
+generateRoleplayAttributes.text=Generate Random Roleplay Attributes
addMinimumComplement.text=Add minimum complement
addMinimumComplementRandom.text=Random
addMinimumComplementElite.text=Elite
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
index b629d9a3b1f..e38419c3ac3 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelRole.java
@@ -47,103 +47,99 @@ public enum PersonnelRole {
// region Enum Declarations
/**
* Individual roles with corresponding name texts and mnemonics.
- *
- *
Note: The attribute score modifiers assume a default attribute score of 5. I opted to only include
- * this information as modifiers, as it means if we ever change what the default score is, the ratios will remain
- * correct.
*/
// I used an average of the modifiers from the MekWarrior, Hot Shot, and Grizzled Veteran ATOW Archetypes
- MEKWARRIOR(true, KeyEvent.VK_M, -1, 0, 1, 1, -1, -1, -1),
+ MEKWARRIOR(true, KeyEvent.VK_M, 4, 5, 6, 6, 4, 4, 4),
// I used an average of the modifiers from the MekWarrior, and Aerospace Pilot ATOW Archetypes
- LAM_PILOT(true, KeyEvent.VK_UNDEFINED, -1, -1, 1, 1, -1, -1, -1),
+ LAM_PILOT(true, KeyEvent.VK_UNDEFINED, 4, 4, 6, 6, 4, 4, 41),
// ATOW: Tanker Archetype
- GROUND_VEHICLE_DRIVER(true, KeyEvent.VK_V, -1, 0, 0, +1, -1, -1, -1),
+ GROUND_VEHICLE_DRIVER(true, KeyEvent.VK_V, 4, 5, 5, 6, 4, 4, 4),
// ATOW: Tanker Archetype
- NAVAL_VEHICLE_DRIVER(true, KeyEvent.VK_N, -1, 0, 0, +1, -1, -1, -1),
+ NAVAL_VEHICLE_DRIVER(true, KeyEvent.VK_N, 4, 5, 5, 6, 4, 4, 4),
// ATOW: Companion Chopper Pilot Archetype
- VTOL_PILOT(true, KeyEvent.VK_UNDEFINED, -1, -1, 0, 0, -1, -1, -1),
+ VTOL_PILOT(true, KeyEvent.VK_UNDEFINED, 4, 4, 5, 5, 4, 4, 4),
// ATOW: Tanker Archetype
- VEHICLE_GUNNER(true, KeyEvent.VK_G, -1, 0, 0, +1, -1, -1, -1),
+ VEHICLE_GUNNER(true, KeyEvent.VK_G, 4, 5, 5, 6, 4, 4, 4),
// ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
// Technician skill)
- VEHICLE_CREW(true, KeyEvent.VK_UNDEFINED, 0, -1, 0, -2, 0, -1, -2),
+ VEHICLE_CREW(true, KeyEvent.VK_UNDEFINED, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Aerospace Pilot Archetype
- AEROSPACE_PILOT(true, KeyEvent.VK_A, -3, -2, 0, 0, -1, -1, 0),
+ AEROSPACE_PILOT(true, KeyEvent.VK_A, 2, 3, 5, 5, 4, 4, 0),
// ATOW: Aerospace Pilot Archetype
- CONVENTIONAL_AIRCRAFT_PILOT(true, KeyEvent.VK_C, -3, -2, 0, 0, -1, -1, 0),
+ CONVENTIONAL_AIRCRAFT_PILOT(true, KeyEvent.VK_C, 2, 3, 5, 5, 4, 4, 0),
// ATOW: Aerospace Pilot Archetype (most ProtoMek pilots are Aerospace Sibkbo washouts, so this made the most sense)
- PROTOMEK_PILOT(true, KeyEvent.VK_P, -3, -2, 0, 0, -1, -1, 0),
+ PROTOMEK_PILOT(true, KeyEvent.VK_P, 2, 3, 5, 5, 4, 4, 0),
// ATOW: Elemental Archetype
- BATTLE_ARMOUR(true, true, KeyEvent.VK_B, +2, +1, -1, 0, -2, -1, -2),
+ BATTLE_ARMOUR(true, true, KeyEvent.VK_B, 7, 6, 4, 0, 3, 4, 3),
// ATOW: Renegade Warrior Archetype
- SOLDIER(true, KeyEvent.VK_S, 0, 0, -1, 0, -1, +1, -2),
+ SOLDIER(true, KeyEvent.VK_S, 5, 5, 4, 5, 4, 6, 3),
// ATOW: Tanker Archetype
- VESSEL_PILOT(true, KeyEvent.VK_I, -1, 0, 0, +1, -1, -1, -1),
+ VESSEL_PILOT(true, KeyEvent.VK_I, 4, 5, 5, 6, 4, 4, 4),
// ATOW: Tanker Archetype
- VESSEL_GUNNER(true, KeyEvent.VK_U, -1, 0, 0, +1, -1, -1, -1),
+ VESSEL_GUNNER(true, KeyEvent.VK_U, 4, 5, 5, 6, 4, 4, 4),
// ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
// Technician skill)
- VESSEL_CREW(true, KeyEvent.VK_W, 0, -1, 0, -2, 0, -1, -2),
+ VESSEL_CREW(true, KeyEvent.VK_W, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Battlefield Tech Archetype
- VESSEL_NAVIGATOR(true, KeyEvent.VK_Y, 0, -1, 0, -2, 0, -1, -2),
+ VESSEL_NAVIGATOR(true, KeyEvent.VK_Y, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
// Technician skill)
- MEK_TECH(false, KeyEvent.VK_T, 0, -1, 0, -2, 0, -1, -2),
+ MEK_TECH(false, KeyEvent.VK_T, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
// Technician skill)
- MECHANIC(false, KeyEvent.VK_E, 0, -1, 0, -2, 0, -1, -2),
+ MECHANIC(false, KeyEvent.VK_E, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
// Technician skill)
- AERO_TEK(false, KeyEvent.VK_O, 0, -1, 0, -2, 0, -1, -2),
+ AERO_TEK(false, KeyEvent.VK_O, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
// Technician skill)
- BA_TECH(false, KeyEvent.VK_UNDEFINED, 0, -1, 0, -2, 0, -1, -2),
+ BA_TECH(false, KeyEvent.VK_UNDEFINED, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Battlefield Tech Archetype (but with the reduced Dexterity removed, as that's a Linked Attribute for the
// Technician skill)
- ASTECH(false, KeyEvent.VK_UNDEFINED, 0, -1, 0, -2, 0, -1, -2),
+ ASTECH(false, KeyEvent.VK_UNDEFINED, 5, 4, 5, 3, 5, 4, 3),
// ATOW: Communications Specialist Archetype (this might seem like an odd choice, but the Attributes for this Archetype
// work really well for this profession
- DOCTOR(false, KeyEvent.VK_D, -2, -1, -1, 0, 1, -1, -1),
+ DOCTOR(false, KeyEvent.VK_D, 3, 4, 4, 5, 6, 4, 4),
// ATOW: Communications Specialist Archetype (this might seem like an odd choice, but the Attributes for this Archetype
// work really well for this profession
- MEDIC(false, KeyEvent.VK_UNDEFINED, -2, -1, -1, 0, 1, -1, -1),
+ MEDIC(false, KeyEvent.VK_UNDEFINED, 3, 4, 4, 5, 6, 4, 4),
// ATOW: Faceman Archetype
- ADMINISTRATOR_COMMAND(false, KeyEvent.VK_UNDEFINED, -2, -2, -2, -1, 1, -2, 1),
+ ADMINISTRATOR_COMMAND(false, KeyEvent.VK_UNDEFINED, 3, 3, 3, 4, 6, 3, 5),
// ATOW: Faceman Archetype
- ADMINISTRATOR_LOGISTICS(false, KeyEvent.VK_L, -2, -2, -2, -1, 1, -2, 1),
+ ADMINISTRATOR_LOGISTICS(false, KeyEvent.VK_L, 3, 3, 3, 4, 6, 3, 5),
// ATOW: Faceman Archetype
- ADMINISTRATOR_TRANSPORT(false, KeyEvent.VK_R, -2, -2, -2, -1, 1, -2, 1),
+ ADMINISTRATOR_TRANSPORT(false, KeyEvent.VK_R, 3, 3, 3, 4, 6, 3, 5),
// ATOW: Faceman Archetype
- ADMINISTRATOR_HR(false, KeyEvent.VK_H, -2, -2, -2, -1, 1, -2, 1),
+ ADMINISTRATOR_HR(false, KeyEvent.VK_H, 3, 3, 3, 4, 6, 3, 5),
// No archetype, but ATOW pg 35 states that the Attribute scores for an average person are 4
- DEPENDENT(false, KeyEvent.VK_UNDEFINED, -1, -1, -1, -1, -1, -1, -1),
+ DEPENDENT(false, KeyEvent.VK_UNDEFINED, 4, 4, 4, 4, 4, 4, 4),
// If we're generating a character without a Profession, we're just going to leave them with middle of the road
// Attribute scores (5 in everything)
@@ -168,7 +164,7 @@ public enum PersonnelRole {
// region Constructors
PersonnelRole(final int mnemonic) {
- this(false, false, mnemonic, 0, 0, 0, 0, 0, 0, 0);
+ this(false, false, mnemonic, 5, 5, 5, 5, 5, 5, 5);
}
PersonnelRole(final boolean isCombat, final int mnemonic, final int strength, final int body, final int dexterity,
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
index 93f815e54e4..f984272ec08 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
@@ -170,9 +170,9 @@ public void generateAttributes(Person person) {
}
// Profession && Phenotype adjustments
- int attributeModifier = profession.getAttributeModifier(attribute);
- attributeModifier += phenotype.getAttributeModifier(attribute);
- person.changeAttributeScore(attribute, attributeModifier);
+ int baseAttributeScore = profession.getAttributeModifier(attribute);
+ int attributeModifier = phenotype.getAttributeModifier(attribute);
+ person.setAttributeScore(attribute, baseAttributeScore + attributeModifier);
// Attribute randomization
int roll = d6();
diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java
index 5e02956fd21..54707751f26 100644
--- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java
+++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java
@@ -213,6 +213,7 @@ public class PersonnelTableMouseAdapter extends JPopupMenuAdapter {
private static final String CMD_PERSONALITY = "PERSONALITY";
private static final String CMD_ADD_RANDOM_ABILITY = "ADD_RANDOM_ABILITY";
private static final String CMD_GENERATE_ROLEPLAY_SKILLS = "GENERATE_ROLEPLAY_SKILLS";
+ private static final String CMD_GENERATE_ROLEPLAY_ATTRIBUTES = "GENERATE_ROLEPLAY_ATTRIBUTES";
private static final String CMD_FREE = "FREE";
private static final String CMD_EXECUTE = "EXECUTE";
@@ -1367,6 +1368,15 @@ public void actionPerformed(ActionEvent action) {
}
break;
}
+ case CMD_GENERATE_ROLEPLAY_ATTRIBUTES: {
+ RandomSkillPreferences skillPreferences = getCampaign().getRandomSkillPreferences();
+ AbstractSkillGenerator skillGenerator = new DefaultSkillGenerator(skillPreferences);
+ for (Person person : people) {
+ skillGenerator.generateAttributes(person);
+ MekHQ.triggerEvent(new PersonChangedEvent(person));
+ }
+ break;
+ }
// region Randomization Menu
case CMD_RANDOM_NAME: {
@@ -3631,6 +3641,11 @@ protected Optional createPopupMenu() {
menuItem.addActionListener(this);
menu.add(menuItem);
+ menuItem = new JMenuItem(resources.getString("generateRoleplayAttributes.text"));
+ menuItem.setActionCommand(CMD_GENERATE_ROLEPLAY_ATTRIBUTES);
+ menuItem.addActionListener(this);
+ menu.add(menuItem);
+
JMenu attributesMenu = new JMenu(resources.getString("spendOnAttributes.set"));
for (SkillAttribute attribute : SkillAttribute.values()) {
From fc015ff6718105082a80915bbf9dd632b7bd2a13 Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Sun, 6 Apr 2025 17:57:47 -0500
Subject: [PATCH 07/10] - Changed the `generateRoleplayAttributes.text` label
from "Generate Random Roleplay Attributes" to "Reset Roleplay Attributes."
---
MekHQ/resources/mekhq/resources/GUI.properties | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MekHQ/resources/mekhq/resources/GUI.properties b/MekHQ/resources/mekhq/resources/GUI.properties
index 9fac966fd81..6ece476658a 100644
--- a/MekHQ/resources/mekhq/resources/GUI.properties
+++ b/MekHQ/resources/mekhq/resources/GUI.properties
@@ -282,7 +282,7 @@ regenerateLoyalty.text=Regenerate Loyalty
regeneratePersonality.text=Regenerate Personality
addRandomSPA.text=Add Random SPA
generateRoleplaySkills.text=Generate Random Roleplay Skills
-generateRoleplayAttributes.text=Generate Random Roleplay Attributes
+generateRoleplayAttributes.text=Reset Roleplay Attributes
addMinimumComplement.text=Add minimum complement
addMinimumComplementRandom.text=Random
addMinimumComplementElite.text=Elite
From e3abdc900584da107692ac2d364e757638269bc6 Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Wed, 9 Apr 2025 18:11:40 -0500
Subject: [PATCH 08/10] Added Attribute Maximums Based on Phenotype and
Exceptional Attribute SPAs
- Introduced a new `AttributeScoreSorter` for comparing "x / y" formatted strings, sorting by primary and secondary values.
- Updated attribute display and sorting in `PersonnelTableModelColumn` to represent both current scores and caps ("x / y").
- Added new "Exceptional Attribute" SPAs to increase attribute caps.
- Modified phenotype definitions in `Phenotype` to include attribute caps specific to each phenotype.
- Adjusted attribute handling logic to respect both phenotype caps and SPA adjustments.
- Enhanced unit tests to verify attribute caps and ensure adherence to defined ranges.
---
MekHQ/data/universe/defaultspa.xml | 68 +++-
.../src/mekhq/campaign/personnel/Person.java | 128 +++---
.../campaign/personnel/PersonnelOptions.java | 16 +
.../campaign/personnel/enums/Phenotype.java | 39 +-
.../generator/DefaultSkillGenerator.java | 4 +-
.../campaign/personnel/skills/Attributes.java | 381 ++++++++++++++----
.../adapter/PersonnelTableMouseAdapter.java | 4 +-
.../gui/enums/PersonnelTableModelColumn.java | 46 ++-
.../gui/sorter/AttributeScoreSorter.java | 92 +++++
.../personnel/skills/AttributesTest.java | 247 +++++++-----
.../enums/PersonnelTableModelColumnTest.java | 124 +++---
11 files changed, 797 insertions(+), 352 deletions(-)
create mode 100644 MekHQ/src/mekhq/gui/sorter/AttributeScoreSorter.java
diff --git a/MekHQ/data/universe/defaultspa.xml b/MekHQ/data/universe/defaultspa.xml
index 21dd7fc6fa4..a8943dc4f87 100644
--- a/MekHQ/data/universe/defaultspa.xml
+++ b/MekHQ/data/universe/defaultspa.xml
@@ -469,6 +469,66 @@
1
+
+ exceptional_attribute_strength
+ Exceptional Attribute - Strength (ATOW)
+
+ 200
+ 1
+
+
+
+ exceptional_attribute_body
+ Exceptional Attribute - Body (ATOW)
+
+ 200
+ 1
+
+
+
+ exceptional_attribute_reflexes
+ Exceptional Attribute - Reflexes (ATOW)
+
+ 200
+ 1
+
+
+
+ exceptional_attribute_dexterity
+ Exceptional Attribute - Dexterity (ATOW)
+
+ 200
+ 1
+
+
+
+ exceptional_attribute_intelligence
+ Exceptional Attribute - Intelligence (ATOW)
+
+ 200
+ 1
+
+
+
+ exceptional_attribute_willpower
+ Exceptional Attribute - Willpower (ATOW)
+
+ 200
+ 1
+
+ eagle_eyes100
@@ -541,9 +601,9 @@
1Unit Reputation is decreased by 1 if this character is the campaign commander.
-A pilot who has Combat Sense rolls three dice per initiative check, keeping the top two rolls.
+ A pilot who has Combat Sense rolls three dice per initiative check, keeping the top two rolls.
-If individual initiative is enabled, this penalty applies only to the pilot's unit. Otherwise, the penalty is applied only if the pilot's unit is the force commander.
+ If individual initiative is enabled, this penalty applies only to the pilot's unit. Otherwise, the penalty is applied only if the pilot's unit is the force commander.
atow_combat_sense
@@ -554,9 +614,9 @@ If individual initiative is enabled, this penalty applies only to the pilot's un
1Unit Reputation is increased by 1 if this character is the campaign commander.
-A pilot who has Combat Sense rolls three dice per initiative check, keeping the top two rolls.
+ A pilot who has Combat Sense rolls three dice per initiative check, keeping the top two rolls.
-If individual initiative is enabled, this bonus applies only to the pilot's unit. Otherwise, the bonus is applied only if the pilot's unit is the force commander.
+ If individual initiative is enabled, this bonus applies only to the pilot's unit. Otherwise, the bonus is applied only if the pilot's unit is the force commander.
Gunnery/Mek::Veteran
diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java
index 17a1d6ee168..39c2a7d2954 100644
--- a/MekHQ/src/mekhq/campaign/personnel/Person.java
+++ b/MekHQ/src/mekhq/campaign/personnel/Person.java
@@ -34,6 +34,8 @@
import static megamek.common.Compute.randomInt;
import static megamek.common.enums.SkillLevel.REGULAR;
import static mekhq.campaign.personnel.enums.BloodGroup.getRandomBloodGroup;
+import static mekhq.campaign.personnel.skills.Attributes.DEFAULT_ATTRIBUTE_SCORE;
+import static mekhq.campaign.personnel.skills.Attributes.MAXIMUM_ATTRIBUTE_SCORE;
import static mekhq.campaign.personnel.skills.SkillType.S_ADMIN;
import java.io.PrintWriter;
@@ -2671,7 +2673,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign campaign, Version
} else if (nodeName.equalsIgnoreCase("becomingBondsmanEndDate")) {
person.becomingBondsmanEndDate = MHQXMLUtility.parseDate(wn2.getTextContent().trim());
} else if (nodeName.equalsIgnoreCase("phenotype")) {
- person.phenotype = Phenotype.parseFromString(wn2.getTextContent().trim());
+ person.phenotype = Phenotype.fromString(wn2.getTextContent().trim());
} else if (nodeName.equalsIgnoreCase("bloodname")) {
person.bloodname = wn2.getTextContent();
} else if (nodeName.equalsIgnoreCase("biography")) {
@@ -4958,67 +4960,72 @@ public Attributes getATOWAttributes() {
}
/**
- * Updates the score of a specific attribute to a new value.
+ * Updates the score for a specific skill attribute.
*
- *
This method modifies the score of an attribute specified by the {@link SkillAttribute} parameter. If the
- * provided attribute is {@code NONE}, no changes will be made. If the attribute is {@code null}, the method logs an
- * error and exits without making changes.
+ *
This method sets the provided score for the given {@link SkillAttribute}. If the attribute is
+ * null or represents "NONE", the method logs a warning and exits without making any changes.
*
- * @param attribute the {@link SkillAttribute} to update. Must not be {@code null}.
- * @param newScore the new score to set for the specified attribute.
+ *
The actual attribute score update is delegated to the underlying attribute handler.
*
- * @since 0.50.5
+ * @param attribute The {@link SkillAttribute} to be updated. Must not be null or "NONE".
+ * @param newScore The new score to assign to the specified skill attribute.
+ *
+ * @author Illiani
+ * @since 0.50.05
*/
public void setAttributeScore(final SkillAttribute attribute, final int newScore) {
- if (attribute == null) {
- logger.error("(setAttributeScore) SkillAttribute is null.");
+ if (attribute == null || attribute == SkillAttribute.NONE) {
+ logger.warn("(setAttributeScore) SkillAttribute is null or NONE.");
return;
}
- switch (attribute) {
- case NONE -> {
- }
- case STRENGTH -> atowAttributes.setStrength(newScore);
- case BODY -> atowAttributes.setBody(newScore);
- case REFLEXES -> atowAttributes.setReflexes(newScore);
- case DEXTERITY -> atowAttributes.setDexterity(newScore);
- case INTELLIGENCE -> atowAttributes.setIntelligence(newScore);
- case WILLPOWER -> atowAttributes.setWillpower(newScore);
- case CHARISMA -> atowAttributes.setCharisma(newScore);
- }
- ;
+ atowAttributes.setAttributeScore(phenotype, options, attribute, newScore);
}
/**
* Retrieves the score of a specified attribute.
*
- *
The method maps the provided {@link SkillAttribute} to its corresponding attribute in
- * the {@link Attributes} object and returns its value. If the {@link SkillAttribute} is {@code NONE}, the method
- * returns a score of 0. If the {@code attribute} is {@code null}, an error is logged, and the method returns a
- * score of 0.
- *
* @param attribute the {@link SkillAttribute} to retrieve the score for.
*
- * @return the score of the specified attribute, or 0 if the attribute is {@code NONE} or {@code null}.
+ * @return the score of the specified attribute, or {@link Attributes#DEFAULT_ATTRIBUTE_SCORE} if the attribute is
+ * {@code NONE} or {@code null}.
*
* @since 0.50.5
*/
public int getAttributeScore(final SkillAttribute attribute) {
- if (attribute == null) {
- logger.error("(getAttributeScore) SkillAttribute is null.");
- return 0;
+ if (attribute == null || attribute.isNone()) {
+ logger.error("(getAttributeScore) SkillAttribute is null or NONE.");
+ return DEFAULT_ATTRIBUTE_SCORE;
}
- return switch (attribute) {
- case NONE -> 0;
- case STRENGTH -> atowAttributes.getStrength();
- case BODY -> atowAttributes.getBody();
- case REFLEXES -> atowAttributes.getReflexes();
- case DEXTERITY -> atowAttributes.getDexterity();
- case INTELLIGENCE -> atowAttributes.getIntelligence();
- case WILLPOWER -> atowAttributes.getWillpower();
- case CHARISMA -> atowAttributes.getCharisma();
- };
+ return atowAttributes.getAttributeScore(attribute);
+ }
+
+ /**
+ * Retrieves the maximum allowed value (cap) for the specified {@link SkillAttribute}.
+ *
+ *
If the attribute is {@code null} or marked as {@link SkillAttribute#NONE}, a default maximum attribute score
+ * is returned, and a warning is logged.
+ *
+ *
For valid attributes, this method delegates to
+ * {@link Attributes#getAttributeCap(Phenotype, PersonnelOptions, SkillAttribute)}.
+ *
+ * @param attribute The {@link SkillAttribute} for which the maximum value is being retrieved. Must not be
+ * {@code null} or {@link SkillAttribute#NONE}.
+ *
+ * @return The maximum allowed value (cap) for the given attribute. Returns the default maximum value if the input
+ * attribute is invalid.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public int getAttributeCap(final SkillAttribute attribute) {
+ if (attribute == null || attribute.isNone()) {
+ logger.warn("(getAttributeCap) SkillAttribute is null or NONE.");
+ return MAXIMUM_ATTRIBUTE_SCORE;
+ }
+
+ return atowAttributes.getAttributeCap(phenotype, options, attribute);
}
/**
@@ -5037,35 +5044,32 @@ public void setATOWAttributes(final Attributes atowAttributes) {
}
/**
- * Modifies the score of a specified attribute by applying a delta value.
+ * Modifies the score of a specified skill attribute by a given delta value.
*
- *
This method maps the provided {@link SkillAttribute} to its corresponding attribute in the
- * {@link Attributes} object and adjusts its value by the specified delta. If the {@code attribute} is {@code NONE},
- * the method does nothing. If {@code attribute} is {@code null}, an error is logged, and the method returns without
- * performing any operation.
+ *
This method adjusts the current score of the provided {@link SkillAttribute} by adding the specified delta
+ * to it. If the attribute is {@code null} or {@link SkillAttribute#NONE}, a warning is logged, and the method exits
+ * without making any changes.
*
- * @param attribute the {@link SkillAttribute} to modify the score for.
- * @param delta the value to add to (or subtract from) the current score of the specified attribute.
+ *
The new score is computed as the sum of the current score and the delta, and it is passed
+ * to {@link Attributes#setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} to ensure is compiles
+ * with the character's minimum and maximum attribute score values.
*
- * @since 0.50.5
+ * @param attribute The {@link SkillAttribute} whose score is to be modified. Must not be null.
+ * @param delta The value to add to the current score of the specified skill attribute.
+ *
+ * @author Illiani
+ * @since 0.50.05
*/
public void changeAttributeScore(final SkillAttribute attribute, final int delta) {
- if (attribute == null) {
- logger.error("(changeAttributeScore) SkillAttribute is null.");
+ if (attribute == null || attribute.isNone()) {
+ logger.warn("(changeAttributeScore) SkillAttribute is null or NONE.");
return;
}
- switch (attribute) {
- case NONE -> {
- }
- case STRENGTH -> atowAttributes.changeStrength(delta);
- case BODY -> atowAttributes.changeBody(delta);
- case REFLEXES -> atowAttributes.changeReflexes(delta);
- case DEXTERITY -> atowAttributes.changeDexterity(delta);
- case INTELLIGENCE -> atowAttributes.changeIntelligence(delta);
- case WILLPOWER -> atowAttributes.changeWillpower(delta);
- case CHARISMA -> atowAttributes.changeCharisma(delta);
- }
+ int current = atowAttributes.getAttributeScore(attribute);
+ int newScore = current + delta;
+
+ setAttributeScore(attribute, newScore);
}
public void resetSkillTypes() {
diff --git a/MekHQ/src/mekhq/campaign/personnel/PersonnelOptions.java b/MekHQ/src/mekhq/campaign/personnel/PersonnelOptions.java
index 706898bc443..604e6cbfd48 100644
--- a/MekHQ/src/mekhq/campaign/personnel/PersonnelOptions.java
+++ b/MekHQ/src/mekhq/campaign/personnel/PersonnelOptions.java
@@ -64,6 +64,14 @@ public class PersonnelOptions extends PilotOptions {
public static final String TECH_MAINTAINER = "tech_maintainer";
public static final String FLAW_GLASS_JAW = "flaw_glass_jaw";
+ public static final String EXCEPTIONAL_ATTRIBUTE_STRENGTH = "exceptional_attribute_strength";
+ public static final String EXCEPTIONAL_ATTRIBUTE_BODY = "exceptional_attribute_body";
+ public static final String EXCEPTIONAL_ATTRIBUTE_REFLEXES = "exceptional_attribute_reflexes";
+ public static final String EXCEPTIONAL_ATTRIBUTE_DEXTERITY = "exceptional_attribute_dexterity";
+ public static final String EXCEPTIONAL_ATTRIBUTE_INTELLIGENCE = "exceptional_attribute_intelligence";
+ public static final String EXCEPTIONAL_ATTRIBUTE_WILLPOWER = "exceptional_attribute_willpower";
+ public static final String EXCEPTIONAL_ATTRIBUTE_CHARISMA = "exceptional_attribute_charisma";
+
@Override
public void initialize() {
super.initialize();
@@ -108,6 +116,14 @@ public void initialize() {
addOption(l3a, TECH_MAINTAINER, false);
addOption(l3a, FLAW_GLASS_JAW, false);
+ addOption(l3a, EXCEPTIONAL_ATTRIBUTE_STRENGTH, false);
+ addOption(l3a, EXCEPTIONAL_ATTRIBUTE_BODY, false);
+ addOption(l3a, EXCEPTIONAL_ATTRIBUTE_REFLEXES, false);
+ addOption(l3a, EXCEPTIONAL_ATTRIBUTE_DEXTERITY, false);
+ addOption(l3a, EXCEPTIONAL_ATTRIBUTE_INTELLIGENCE, false);
+ addOption(l3a, EXCEPTIONAL_ATTRIBUTE_WILLPOWER, false);
+ addOption(l3a, EXCEPTIONAL_ATTRIBUTE_CHARISMA, false);
+
addOption(edge, EDGE_MEDICAL, true);
addOption(edge, EDGE_REPAIR_BREAK_PART, true);
addOption(edge, EDGE_REPAIR_FAILED_REFIT, true);
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java b/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java
index 4e90525dd70..4a9b498f723 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/Phenotype.java
@@ -34,6 +34,7 @@
import megamek.codeUtilities.MathUtility;
import megamek.logging.MMLogger;
+import mekhq.campaign.personnel.skills.Attributes;
import mekhq.campaign.personnel.skills.enums.SkillAttribute;
/**
@@ -46,24 +47,24 @@ public enum Phenotype {
/**
* Individual external phenotypes.
*/
- MEKWARRIOR(true, true, 0, 0, 1, 1, new ArrayList<>()),
- ELEMENTAL(true, true, 2, 1, -1, 0, List.of("atow_toughness")),
- AEROSPACE(true, true, -1, -1, +2, +2, List.of("flaw_glass_jaw")),
+ MEKWARRIOR(true, true, 0, 0, 1, 1, new Attributes(8, 8, 9, 9, 8, 8, 9), new ArrayList<>()),
+ ELEMENTAL(true, true, 2, 1, -1, 0, new Attributes(9, 9, 8, 7, 8, 9, 8), List.of("atow_toughness")),
+ AEROSPACE(true, true, -1, -1, +2, +2, new Attributes(7, 7, 9, 9, 9, 8, 8), List.of("flaw_glass_jaw")),
// ATOW doesn't cover a vehicle phenotype, but as the linked attributes for vehicle skills are also reflexes and
- // dexterity I copied the MekWarrior phenotype
- VEHICLE(true, true, 0, 0, 1, 1, new ArrayList<>()),
+ // dexterity, I copied the MekWarrior phenotype
+ VEHICLE(true, true, 0, 0, 1, 1, new Attributes(8, 8, 9, 9, 8, 8, 9), new ArrayList<>()),
// According to my research, ProtoMek pilots are normally just Aerospace washouts, so I'm assuming they'd have the
// same phenotype modifiers.
- PROTOMEK(true, true, -1, -1, +2, +2, List.of("flaw_glass_jaw")),
+ PROTOMEK(true, true, -1, -1, +2, +2, new Attributes(7, 7, 9, 9, 9, 8, 8), List.of("flaw_glass_jaw")),
// Copying the MekWarrior phenotype, same reasons as above.
- NAVAL(true, true, 0, 0, 1, 1, new ArrayList<>()),
+ NAVAL(true, true, 0, 0, 1, 1, new Attributes(8, 8, 9, 9, 8, 8, 9), new ArrayList<>()),
/**
* Individual internal phenotypes.
*/
// Internal Phenotypes
- NONE(false, false, 0, 0, 0, 0, new ArrayList<>()),
- GENERAL(false, false, 0, 0, 0, 0, new ArrayList<>());
+ NONE(false, false, 0, 0, 0, 0, new Attributes(8, 8, 8, 8, 8, 8, 9), new ArrayList<>()),
+ GENERAL(false, false, 0, 0, 0, 0, new Attributes(8, 8, 8, 8, 8, 8, 9), new ArrayList<>());
// endregion Enum Declarations
// region Variable Declarations
@@ -76,28 +77,44 @@ public enum Phenotype {
private final int body;
private final int reflexes;
private final int dexterity;
+ private final Attributes attributeCaps;
private final List bonusTraits;
// endregion Variable Declarations
// region Constructors
Phenotype() {
- this(false, false, 0, 0, 0, 0, new ArrayList<>());
+ this(false, false, 0, 0, 0, 0, new Attributes(8, 8, 8, 8, 8, 8, 9), new ArrayList<>());
}
Phenotype(final boolean isTrueborn, final boolean external, final int strength, final int body, final int reflexes,
- final int dexterity, final List bonusTraits) {
+ final int dexterity, final Attributes attributeCaps, final List bonusTraits) {
this.isTrueborn = isTrueborn;
this.external = external;
this.strength = strength;
this.body = body;
this.reflexes = reflexes;
this.dexterity = dexterity;
+ this.attributeCaps = attributeCaps;
this.bonusTraits = bonusTraits;
}
// endregion Constructors
// region Getters
+ /**
+ * Retrieves the cap (maximum allowable score) for a specified {@link SkillAttribute}.
+ *
+ * @param attribute The {@link SkillAttribute} for which the cap is requested.
+ *
+ * @return The cap value for the specified skill attribute.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public int getAttributeCap(SkillAttribute attribute) {
+ return attributeCaps.getAttributeScore(attribute);
+ }
+
/**
* @deprecated use {@link #getLabel()} instead
*/
diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
index f984272ec08..5f998bea9da 100644
--- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
+++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java
@@ -28,7 +28,6 @@
package mekhq.campaign.personnel.generator;
import static megamek.common.Compute.d6;
-import static mekhq.campaign.personnel.skills.Attributes.MAXIMUM_ATTRIBUTE_SCORE;
import static mekhq.campaign.personnel.skills.Attributes.MINIMUM_ATTRIBUTE_SCORE;
import static mekhq.campaign.personnel.skills.SkillDeprecationTool.DEPRECATED_SKILLS;
import static mekhq.campaign.personnel.skills.enums.SkillSubType.SUPPORT_COMMAND;
@@ -189,7 +188,8 @@ public void generateAttributes(Person person) {
person.changeAttributeScore(attribute, 1);
if (extraRandomAttributes) {
- while ((d6() == 6) && (person.getAttributeScore(attribute) < MAXIMUM_ATTRIBUTE_SCORE)) {
+ int attributeCap = person.getPhenotype().getAttributeCap(attribute);
+ while ((d6() == 6) && (person.getAttributeScore(attribute) < attributeCap)) {
person.changeAttributeScore(attribute, 1);
}
}
diff --git a/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java b/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
index d54cca120f0..b7f9cab27fb 100644
--- a/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
+++ b/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
@@ -28,11 +28,21 @@
package mekhq.campaign.personnel.skills;
import static megamek.codeUtilities.MathUtility.clamp;
+import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_BODY;
+import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_CHARISMA;
+import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_DEXTERITY;
+import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_INTELLIGENCE;
+import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_REFLEXES;
+import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_STRENGTH;
+import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_WILLPOWER;
import java.io.PrintWriter;
import megamek.codeUtilities.MathUtility;
import megamek.logging.MMLogger;
+import mekhq.campaign.personnel.PersonnelOptions;
+import mekhq.campaign.personnel.enums.Phenotype;
+import mekhq.campaign.personnel.skills.enums.SkillAttribute;
import mekhq.utilities.MHQXMLUtility;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -117,161 +127,303 @@ public Attributes() {
charisma = DEFAULT_ATTRIBUTE_SCORE;
}
+
+ /**
+ * Creates an instance of {@code Attributes} with specified values for each {@link SkillAttribute}.
+ *
+ * @param strength The initial value for the strength {@link SkillAttribute}.
+ * @param body The initial value for the body {@link SkillAttribute}.
+ * @param reflexes The initial value for the reflexes {@link SkillAttribute}.
+ * @param dexterity The initial value for the dexterity {@link SkillAttribute}.
+ * @param intelligence The initial value for the intelligence {@link SkillAttribute}.
+ * @param willpower The initial value for the willpower {@link SkillAttribute}.
+ * @param charisma The initial value for the charisma {@link SkillAttribute}.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public Attributes(int strength, int body, int reflexes, int dexterity, int intelligence, int willpower,
+ int charisma) {
+ this.strength = strength;
+ this.body = body;
+ this.reflexes = reflexes;
+ this.dexterity = dexterity;
+ this.intelligence = intelligence;
+ this.willpower = willpower;
+ this.charisma = charisma;
+ }
+
+ /**
+ * Initializes all attributes with the same specified value.
+ *
+ *
This constructor is primarily intended to facilitate testing by allowing all attribute fields to be set
+ * to the same value with a single argument.
+ *
+ * @param singleValue The value to be assigned to all attribute fields, such as strength, body, reflexes, dexterity,
+ * intelligence, willpower, and charisma.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public Attributes(int singleValue) {
+ this.strength = singleValue;
+ this.body = singleValue;
+ this.reflexes = singleValue;
+ this.dexterity = singleValue;
+ this.intelligence = singleValue;
+ this.willpower = singleValue;
+ this.charisma = singleValue;
+ }
+
// Getters and Setters
/**
- * @return the current strength value.
+ * Retrieves the score for a given attribute.
*
- * @since 0.50.5
+ *
If an invalid or unsupported {@link SkillAttribute} is provided, this method logs an error and returns a
+ * default value of {@link Attributes#DEFAULT_ATTRIBUTE_SCORE}.
+ *
+ * @param attribute The {@link SkillAttribute} whose score should be retrieved.
+ *
+ * @return The score corresponding to the specified skill attribute, or {@link Attributes#DEFAULT_ATTRIBUTE_SCORE}
+ * if the attribute is invalid.
+ *
+ * @author Illiani
+ * @since 0.50.05
*/
- public int getStrength() {
- return strength;
+ public int getAttributeScore(SkillAttribute attribute) {
+ if (attribute == null || attribute.isNone()) {
+ logger.warn("(getAttributeScore) attribute is null or NONE.");
+ return DEFAULT_ATTRIBUTE_SCORE;
+ }
+
+ return switch (attribute) {
+ case STRENGTH -> strength;
+ case BODY -> body;
+ case REFLEXES -> reflexes;
+ case DEXTERITY -> dexterity;
+ case INTELLIGENCE -> intelligence;
+ case WILLPOWER -> willpower;
+ case CHARISMA -> charisma;
+ default -> {
+ logger.error("(getAttributeScore) Invalid attribute requested: {}", attribute);
+ yield DEFAULT_ATTRIBUTE_SCORE;
+ }
+ };
}
/**
- * Sets the strength attribute, ensuring it is clamped between the defined minimum and maximum values.
+ * Sets the score for a specific skill attribute while respecting its attribute cap.
*
- * @param strength the new strength value.
+ *
This method updates the score of the provided {@link SkillAttribute} to the specified value. The score is
+ * clamped to ensure it remains within the range of {@link Attributes#MINIMUM_ATTRIBUTE_SCORE} and the calculated
+ * cap for the attribute.
The attribute cap is determined using the provided {@link Phenotype} and may be further influenced by
+ * {@link PersonnelOptions}, such as special abilities or conditions modifying the cap.
+ *
+ *
If the provided {@link SkillAttribute} is null, represents "NONE", or is unrecognized,
+ * the method logs a warning or error and exits without making any changes.
+ *
+ * @param phenotype The {@link Phenotype} object used to derive the attribute cap for the skill.
+ * @param options The {@link PersonnelOptions} containing context-specific modifiers (e.g., special abilities).
+ * @param attribute The {@link SkillAttribute} representing the attribute to update. Must not be null
+ * or "NONE".
+ * @param score The new score to set for the specified attribute. This value will be clamped within
+ * {@link Attributes#MINIMUM_ATTRIBUTE_SCORE} and the calculated cap.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public void setAttributeScore(Phenotype phenotype, PersonnelOptions options, SkillAttribute attribute, int score) {
+ if (attribute == null || attribute.isNone()) {
+ logger.warn("(setAttributeScore) attribute is null or NONE.");
+ return;
+ }
+
+ int cap = getAttributeCap(phenotype, options, attribute);
+
+ // This ensures we never fall outside the hard boundaries, no matter how many SPAs or other weirdness the
+ // player piles on.
+ cap = clamp(cap, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
+
+ switch (attribute) {
+ case STRENGTH -> strength = clamp(score, MINIMUM_ATTRIBUTE_SCORE, cap);
+ case BODY -> body = clamp(score, MINIMUM_ATTRIBUTE_SCORE, cap);
+ case REFLEXES -> reflexes = clamp(score, MINIMUM_ATTRIBUTE_SCORE, cap);
+ case DEXTERITY -> dexterity = clamp(score, MINIMUM_ATTRIBUTE_SCORE, cap);
+ case INTELLIGENCE -> intelligence = clamp(score, MINIMUM_ATTRIBUTE_SCORE, cap);
+ case WILLPOWER -> willpower = clamp(score, MINIMUM_ATTRIBUTE_SCORE, cap);
+ case CHARISMA -> charisma = clamp(score, MINIMUM_ATTRIBUTE_SCORE, cap);
+ default -> logger.error("(setAttributeScore) Invalid attribute requested: {}", attribute);
+ }
+ }
+
+ /**
+ * Determines the maximum allowable value (cap) for the specified skill attribute.
+ *
+ *
This method calculates the cap for the given {@link SkillAttribute} based on the provided {@link Phenotype}
+ * and {@link PersonnelOptions}. The base cap is retrieved from the {@code phenotype}, and adjustments are applied
+ * if the character has specific traits (flags in {@code options}) that raise the cap for certain attributes.
+ *
+ *
If the attribute is invalid or unrecognized, an error message is logged, and a default value of {@code 0} is
+ * used.
+ *
+ * @param phenotype The {@link Phenotype} that provides the base cap for the given attribute. Must not be
+ * null.
+ * @param options The {@link PersonnelOptions} that may modify the attribute cap based on specific traits. Must
+ * not be null.
+ * @param attribute The {@link SkillAttribute} whose maximum value is being determined. Must not be
+ * null.
+ *
+ * @return The maximum allowable value (cap) for the given attribute, based on the phenotype and applicable trait
+ * modifiers.
+ *
+ * @author Illiani
+ * @since 0.50.05
+ */
+ public int getAttributeCap(Phenotype phenotype, PersonnelOptions options, SkillAttribute attribute) {
+ // This determines the base cap
+ int cap = phenotype.getAttributeCap(attribute);
+
+ // This is where you'd use options to verify if a character has SPAs that modify their maximum attribute score
+ boolean hasExceptionalStrength = options.booleanOption(EXCEPTIONAL_ATTRIBUTE_STRENGTH);
+ boolean hasFreakishStrength = options.booleanOption(MUTATION_FREAKISH_STRENGTH);
+ boolean hasExceptionalBody = options.booleanOption(EXCEPTIONAL_ATTRIBUTE_BODY);
+ boolean hasExceptionalReflexes = options.booleanOption(EXCEPTIONAL_ATTRIBUTE_REFLEXES);
+ boolean hasExceptionalDexterity = options.booleanOption(EXCEPTIONAL_ATTRIBUTE_DEXTERITY);
+ boolean hasExceptionalIntelligence = options.booleanOption(EXCEPTIONAL_ATTRIBUTE_INTELLIGENCE);
+ boolean hasExceptionalWillpower = options.booleanOption(EXCEPTIONAL_ATTRIBUTE_WILLPOWER);
+ boolean hasExceptionalCharisma = options.booleanOption(EXCEPTIONAL_ATTRIBUTE_CHARISMA);
+
+ cap += switch (attribute) {
+ case STRENGTH -> {
+ int modifier = hasExceptionalStrength ? 1 : 0;
+ modifier += hasFreakishStrength ? 1 : 0;
+ yield modifier;
+ }
+ case BODY -> hasExceptionalBody ? 1 : 0;
+ case DEXTERITY -> hasExceptionalReflexes ? 1 : 0;
+ case REFLEXES -> hasExceptionalDexterity ? 1 : 0;
+ case INTELLIGENCE -> hasExceptionalIntelligence ? 1 : 0;
+ case WILLPOWER -> hasExceptionalWillpower ? 1 : 0;
+ case CHARISMA -> hasExceptionalCharisma ? 1 : 0;
+ default -> {
+ logger.error("(setAttributeScore) Invalid attribute requested for cap modifier: {}", attribute);
+ yield 0;
+ }
+ };
+ return cap;
+ }
+
+ /**
+ * @deprecated use {@link #getAttributeScore(SkillAttribute)} instead
+ */
+ @Deprecated(since = "0.50.5", forRemoval = true)
+ public int getStrength() {
+ return strength;
+ }
+
+ /**
+ * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void setStrength(int strength) {
this.strength = clamp(strength, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
}
/**
- * @return the current body value.
- *
- * @since 0.50.5
+ * @deprecated use {@link #getAttributeScore(SkillAttribute)} instead
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public int getBody() {
return body;
}
-
/**
- * Sets the body attribute, ensuring it is clamped between the defined minimum and maximum values.
- *
- * @param body the new body value.
- *
- * @see #MINIMUM_ATTRIBUTE_SCORE
- * @see #MAXIMUM_ATTRIBUTE_SCORE
- * @since 0.50.5
+ * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void setBody(int body) {
this.body = clamp(body, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
}
/**
- * @return the current reflexes value.
- *
- * @since 0.50.5
+ * @deprecated use {@link #getAttributeScore(SkillAttribute)} instead
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public int getReflexes() {
return reflexes;
}
-
/**
- * Sets the reflexes attribute, ensuring it is clamped between the defined minimum and maximum values.
- *
- * @param reflexes the new reflexes value.
- *
- * @see #MINIMUM_ATTRIBUTE_SCORE
- * @see #MAXIMUM_ATTRIBUTE_SCORE
- * @since 0.50.5
+ * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void setReflexes(int reflexes) {
this.reflexes = clamp(reflexes, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
}
/**
- * @return the current dexterity value.
- *
- * @since 0.50.5
+ * @deprecated use {@link #getAttributeScore(SkillAttribute)} instead
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public int getDexterity() {
return dexterity;
}
-
/**
- * Sets the dexterity attribute, ensuring it is clamped between the defined minimum and maximum values.
- *
- * @param dexterity the new dexterity value.
- *
- * @see #MINIMUM_ATTRIBUTE_SCORE
- * @see #MAXIMUM_ATTRIBUTE_SCORE
- * @since 0.50.5
+ * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void setDexterity(int dexterity) {
this.dexterity = clamp(dexterity, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
}
/**
- * @return the current intelligence value.
- *
- * @since 0.50.5
+ * @deprecated use {@link #getAttributeScore(SkillAttribute)} instead
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public int getIntelligence() {
return intelligence;
}
/**
- * Sets the intelligence attribute, ensuring it is clamped between the defined minimum and maximum values.
- *
- * @param intelligence the new intelligence value.
- *
- * @see #MINIMUM_ATTRIBUTE_SCORE
- * @see #MAXIMUM_ATTRIBUTE_SCORE
- * @since 0.50.5
+ * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void setIntelligence(int intelligence) {
this.intelligence = clamp(intelligence, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
}
/**
- * @return the current willpower value.
- *
- * @since 0.50.5
+ * @deprecated use {@link #getAttributeScore(SkillAttribute)} instead
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public int getWillpower() {
return willpower;
}
/**
- * Sets the willpower attribute, ensuring it is clamped between the defined minimum and maximum values.
- *
- * @param willpower the new willpower value.
- *
- * @see #MINIMUM_ATTRIBUTE_SCORE
- * @see #MAXIMUM_ATTRIBUTE_SCORE
- * @since 0.50.5
+ * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void setWillpower(int willpower) {
this.willpower = clamp(willpower, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
}
/**
- * @return the current charisma value.
- *
- * @since 0.50.5
+ * @deprecated use {@link #getAttributeScore(SkillAttribute)} instead
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public int getCharisma() {
return charisma;
}
/**
- * Sets the charisma attribute, ensuring it is clamped between the defined minimum and maximum values.
- *
- * @param charisma the new charisma value.
- *
- * @see #MINIMUM_ATTRIBUTE_SCORE
- * @see #MAXIMUM_ATTRIBUTE_SCORE
- * @since 0.50.5
+ * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void setCharisma(int charisma) {
this.charisma = clamp(charisma, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
}
@@ -279,22 +431,82 @@ public void setCharisma(int charisma) {
// Utility Methods
/**
- * Applies a delta to all attributes, incrementing or decrementing their values by the specified amount while
- * clamping results within bounds.
+ * Adjusts the scores of all skill attributes by a specified delta.
+ *
+ *
This method iterates through all available {@link SkillAttribute} values and applies the given delta to each,
+ * modifying their scores accordingly. Attribute values are clamped within valid bounds as defined by the
+ * {@code changeAttribute} and {@code setAttributeScore} methods, ensuring no invalid scores are set.
*
- * @param delta the value to add to each attribute. A positive delta will increase the attribute scores, while a
- * negative delta will decrease them.
+ *
Attributes marked as {@link SkillAttribute#NONE} are skipped during the iteration and are not modified.
*
+ * @param phenotype The {@link Phenotype} used to determine the caps for all skill attributes.
+ * @param options The {@link PersonnelOptions} containing context-specific modifiers that may affect attribute
+ * caps.
+ * @param delta The value to adjust each attribute's score. A positive delta increases the scores, while a
+ * negative delta decreases them.
+ *
+ * @author Illiani
* @since 0.50.5
*/
- public void changeAllAttributes(int delta) {
- changeStrength(delta);
- changeBody(delta);
- changeReflexes(delta);
- changeDexterity(delta);
- changeIntelligence(delta);
- changeWillpower(delta);
- changeCharisma(delta);
+ public void changeAllAttributes(Phenotype phenotype, PersonnelOptions options, int delta) {
+ if (phenotype == null) {
+ logger.warn("(changeAllAttributes) phenotype is null.");
+ return;
+ }
+
+ if (options == null) {
+ logger.warn("(changeAllAttributes) options is null.");
+ return;
+ }
+
+ for (SkillAttribute attribute : SkillAttribute.values()) {
+ if (attribute.isNone()) {
+ continue;
+ }
+
+ changeAttribute(phenotype, options, attribute, delta);
+ }
+ }
+
+ /**
+ * Adjusts the score of a specified skill attribute by a given delta.
+ *
+ *
This method modifies the score of the provided {@link SkillAttribute} by adding the given delta to its
+ * current score. The updated score is passed to
+ * {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} to ensure it complies with the
+ * applicable constraints and caps defined by the provided {@link Phenotype} and {@link PersonnelOptions}.
+ *
+ *
If the {@code phenotype}, {@code options}, or {@code attribute} is null, or if the attribute
+ * represents "NONE", the method logs a warning and exits without making any changes.
+ *
+ * @param phenotype The {@link Phenotype} used to determine the cap for the skill attribute. Must not be
+ * null.
+ * @param options The {@link PersonnelOptions} containing context-specific modifiers that may influence the cap
+ * for the attribute. Must not be null.
+ * @param attribute The {@link SkillAttribute} whose score is to be modified. Must not be null or
+ * "NONE".
+ * @param delta The value to adjust the current score of the attribute, where a positive value increases the
+ * score and a negative value decreases it.
+ */
+ public void changeAttribute(Phenotype phenotype, PersonnelOptions options, SkillAttribute attribute, int delta) {
+ if (phenotype == null) {
+ logger.warn("(changeAttribute) phenotype is null.");
+ return;
+ }
+ if (options == null) {
+ logger.warn("(changeAttribute) options is null.");
+ return;
+ }
+
+ if (attribute == null || attribute.isNone()) {
+ logger.warn("(changeAttribute) attribute is null or NONE.");
+ return;
+ }
+
+ int currentScore = getAttributeScore(attribute);
+ // We defer ensuring this falls within permissible values to setAttributeScore
+ int newScore = currentScore + delta;
+ setAttributeScore(phenotype, options, attribute, newScore);
}
/**
@@ -307,6 +519,7 @@ public void changeAllAttributes(int delta) {
*
* @since 0.50.5
*/
+ @Deprecated(since = "0.50.5", forRemoval = true)
public void changeStrength(int delta) {
strength += delta;
strength = clamp(strength, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java
index 54707751f26..b28c3e6c4b4 100644
--- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java
+++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java
@@ -27,6 +27,7 @@
*/
package mekhq.gui.adapter;
+import static java.lang.Math.min;
import static java.lang.Math.round;
import static megamek.client.ui.WrapLayout.wordWrap;
import static megamek.common.Compute.d6;
@@ -2838,7 +2839,8 @@ protected Optional createPopupMenu() {
String.valueOf(attribute),
String.valueOf(attributeCost)));
menuItem.addActionListener(this);
- menuItem.setEnabled(target <= MAXIMUM_ATTRIBUTE_SCORE && person.getXP() >= attributeCost);
+ int attributeCap = min(person.getPhenotype().getAttributeCap(attribute), MAXIMUM_ATTRIBUTE_SCORE);
+ menuItem.setEnabled(target <= attributeCap && person.getXP() >= attributeCost);
attributesMenuIncrease.add(menuItem);
}
menu.add(attributesMenuIncrease);
diff --git a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java
index c5aca49e5ce..1a91c583983 100644
--- a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java
+++ b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java
@@ -60,6 +60,7 @@
import mekhq.campaign.randomEvents.personalities.enums.Social;
import mekhq.campaign.unit.Unit;
import mekhq.campaign.universe.Planet;
+import mekhq.gui.sorter.AttributeScoreSorter;
import mekhq.gui.sorter.BonusSorter;
import mekhq.gui.sorter.DateStringComparator;
import mekhq.gui.sorter.FormattedNumberSorter;
@@ -531,7 +532,12 @@ public boolean isPersonality() {
public String getCellValue(final Campaign campaign, final PersonnelMarket personnelMarket, final Person person,
final boolean loadAssignmentFromMarket, final boolean groupByUnit) {
- PersonnelOptions options = person.getOptions();
+ final PersonnelOptions options = person.getOptions();
+
+ // We define these here, as they're used in multiple cases
+ int currentAttributeValue;
+ int attributeCap;
+
String sign;
switch (this) {
@@ -895,19 +901,33 @@ public String getCellValue(final Campaign campaign, final PersonnelMarket person
return String.valueOf(reasoning.ordinal());
case STRENGTH:
- return String.valueOf(person.getAttributeScore(SkillAttribute.STRENGTH));
+ currentAttributeValue = person.getAttributeScore(SkillAttribute.STRENGTH);
+ attributeCap = person.getAttributeCap(SkillAttribute.STRENGTH);
+ return currentAttributeValue + " / " + attributeCap;
case BODY:
- return String.valueOf(person.getAttributeScore(SkillAttribute.BODY));
+ currentAttributeValue = person.getAttributeScore(SkillAttribute.BODY);
+ attributeCap = person.getAttributeCap(SkillAttribute.BODY);
+ return currentAttributeValue + " / " + attributeCap;
case REFLEXES:
- return String.valueOf(person.getAttributeScore(SkillAttribute.REFLEXES));
+ currentAttributeValue = person.getAttributeScore(SkillAttribute.REFLEXES);
+ attributeCap = person.getAttributeCap(SkillAttribute.REFLEXES);
+ return currentAttributeValue + " / " + attributeCap;
case DEXTERITY:
- return String.valueOf(person.getAttributeScore(SkillAttribute.DEXTERITY));
+ currentAttributeValue = person.getAttributeScore(SkillAttribute.DEXTERITY);
+ attributeCap = person.getAttributeCap(SkillAttribute.DEXTERITY);
+ return currentAttributeValue + " / " + attributeCap;
case INTELLIGENCE:
- return String.valueOf(person.getAttributeScore(SkillAttribute.INTELLIGENCE));
+ currentAttributeValue = person.getAttributeScore(SkillAttribute.INTELLIGENCE);
+ attributeCap = person.getAttributeCap(SkillAttribute.INTELLIGENCE);
+ return currentAttributeValue + " / " + attributeCap;
case WILLPOWER:
- return String.valueOf(person.getAttributeScore(SkillAttribute.WILLPOWER));
+ currentAttributeValue = person.getAttributeScore(SkillAttribute.WILLPOWER);
+ attributeCap = person.getAttributeCap(SkillAttribute.WILLPOWER);
+ return currentAttributeValue + " / " + attributeCap;
case CHARISMA:
- return String.valueOf(person.getAttributeScore(SkillAttribute.CHARISMA));
+ currentAttributeValue = person.getAttributeScore(SkillAttribute.CHARISMA);
+ attributeCap = person.getAttributeCap(SkillAttribute.CHARISMA);
+ return currentAttributeValue + " / " + attributeCap;
default:
return "UNIMPLEMENTED";
}
@@ -1156,14 +1176,8 @@ public Comparator> getComparator(final Campaign campaign) {
SPA_COUNT,
IMPLANT_COUNT,
LOYALTY,
- REASONING,
- STRENGTH,
- BODY,
- REFLEXES,
- DEXTERITY,
- INTELLIGENCE,
- WILLPOWER,
- CHARISMA -> new IntegerStringSorter();
+ REASONING -> new IntegerStringSorter();
+ case STRENGTH, BODY, REFLEXES, DEXTERITY, INTELLIGENCE, WILLPOWER, CHARISMA -> new AttributeScoreSorter();
case SALARY -> new FormattedNumberSorter();
default -> new NaturalOrderComparator();
};
diff --git a/MekHQ/src/mekhq/gui/sorter/AttributeScoreSorter.java b/MekHQ/src/mekhq/gui/sorter/AttributeScoreSorter.java
new file mode 100644
index 00000000000..c2878babe6a
--- /dev/null
+++ b/MekHQ/src/mekhq/gui/sorter/AttributeScoreSorter.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2025 The MegaMek Team. All Rights Reserved.
+ *
+ * This file is part of MekHQ.
+ *
+ * MekHQ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (GPL),
+ * version 3 or (at your option) any later version,
+ * as published by the Free Software Foundation.
+ *
+ * MekHQ 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.
+ *
+ * A copy of the GPL should have been included with this project;
+ * if not, see .
+ *
+ * NOTICE: The MegaMek organization is a non-profit group of volunteers
+ * creating free software for the BattleTech community.
+ *
+ * MechWarrior, BattleMech, `Mech and AeroTech are registered trademarks
+ * of The Topps Company, Inc. All Rights Reserved.
+ *
+ * Catalyst Game Labs and the Catalyst Game Labs logo are trademarks of
+ * InMediaRes Productions, LLC.
+ */
+package mekhq.gui.sorter;
+
+import java.util.Comparator;
+
+import megamek.codeUtilities.MathUtility;
+import megamek.logging.MMLogger;
+
+/**
+ * A comparator implementation for sorting strings representing numerical scores in the format "x / y". The sorting is
+ * performed by the first number `x`, and in case of ties, by the second number `y`.
+ *
+ *
This class is typically used for sorting a character's
+ * {@link mekhq.campaign.personnel.skills.enums.SkillAttribute} scores for display in
+ * {@link mekhq.gui.enums.PersonnelTableModelColumn}.
+ */
+public class AttributeScoreSorter implements Comparator {
+ private static final MMLogger logger = MMLogger.create(AttributeScoreSorter.class);
+
+ private final String DIVIDER_STRING = " / ";
+
+ /**
+ * Compares two strings in the format "x / y" for sorting.
+ *
+ *
The comparison is performed as follows:
+ *
+ *
The first numbers (`x` values) from both strings are compared numerically.
+ *
If the `x` values are the same, the second numbers (`y` values) are compared numerically.
+ *
+ *
+ * @param firstString the first string in the format "x / y".
+ * @param secondString the second string in the format "x / y".
+ *
+ * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater
+ * than the second.
+ */
+ @Override
+ public int compare(String firstString, String secondString) {
+ try {
+ // First String
+ String[] firstStringParts = firstString.split(DIVIDER_STRING);
+ int firstStringFirstNumber = MathUtility.parseInt(firstStringParts[0].trim());
+ int firstStringSecondNumber = MathUtility.parseInt(firstStringParts[1].trim());
+
+ // Second String
+ String[] secondStringParts = secondString.split(DIVIDER_STRING);
+ int secondStringFirstNumber = MathUtility.parseInt(secondStringParts[0].trim());
+ int secondStringSecondNumber = MathUtility.parseInt(secondStringParts[1].trim());
+
+ // Compare the first numbers
+ int result = Integer.compare(firstStringFirstNumber, secondStringFirstNumber);
+
+ // If the first numbers are the same, compare the second numbers
+ if (result == 0) {
+ result = Integer.compare(firstStringSecondNumber, secondStringSecondNumber);
+ }
+
+ return result;
+ // This means the strings are malformed and can't be split into two parts using the divider
+ } catch (ArrayIndexOutOfBoundsException e) {
+ logger.error("Error parsing attribute score string: {} or {}", firstString, secondString);
+
+ return 1; // By default, malformed strings go last
+ }
+ }
+}
diff --git a/MekHQ/unittests/mekhq/campaign/personnel/skills/AttributesTest.java b/MekHQ/unittests/mekhq/campaign/personnel/skills/AttributesTest.java
index e52d77a15a6..79ac5656dac 100644
--- a/MekHQ/unittests/mekhq/campaign/personnel/skills/AttributesTest.java
+++ b/MekHQ/unittests/mekhq/campaign/personnel/skills/AttributesTest.java
@@ -27,194 +27,239 @@
*/
package mekhq.campaign.personnel.skills;
+import static java.lang.Math.min;
import static mekhq.campaign.personnel.skills.Attributes.DEFAULT_ATTRIBUTE_SCORE;
import static mekhq.campaign.personnel.skills.Attributes.MAXIMUM_ATTRIBUTE_SCORE;
import static mekhq.campaign.personnel.skills.Attributes.MINIMUM_ATTRIBUTE_SCORE;
+import static mekhq.campaign.personnel.skills.enums.SkillAttribute.BODY;
+import static mekhq.campaign.personnel.skills.enums.SkillAttribute.CHARISMA;
+import static mekhq.campaign.personnel.skills.enums.SkillAttribute.DEXTERITY;
+import static mekhq.campaign.personnel.skills.enums.SkillAttribute.INTELLIGENCE;
+import static mekhq.campaign.personnel.skills.enums.SkillAttribute.REFLEXES;
+import static mekhq.campaign.personnel.skills.enums.SkillAttribute.STRENGTH;
+import static mekhq.campaign.personnel.skills.enums.SkillAttribute.WILLPOWER;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import mekhq.campaign.personnel.PersonnelOptions;
+import mekhq.campaign.personnel.enums.Phenotype;
+import mekhq.campaign.personnel.skills.enums.SkillAttribute;
import org.junit.jupiter.api.Test;
public class AttributesTest {
@Test
public void testDefaultConstructor() {
Attributes attributes = new Attributes();
- assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getStrength());
- assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getBody());
- assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getReflexes());
- assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getDexterity());
- assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getIntelligence());
- assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getWillpower());
- assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getCharisma());
+ assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getAttributeScore(STRENGTH));
+ assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getAttributeScore(BODY));
+ assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getAttributeScore(REFLEXES));
+ assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getAttributeScore(DEXTERITY));
+ assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getAttributeScore(INTELLIGENCE));
+ assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getAttributeScore(WILLPOWER));
+ assertEquals(DEFAULT_ATTRIBUTE_SCORE, attributes.getAttributeScore(CHARISMA));
}
@Test
public void testSetStrength() {
- Attributes attributes = new Attributes();
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
+
+ final int attributeCap = phenotype.getAttributeCap(STRENGTH);
- attributes.setStrength(MAXIMUM_ATTRIBUTE_SCORE + 1);
- assertEquals(MAXIMUM_ATTRIBUTE_SCORE, attributes.getStrength());
+ attributes.setAttributeScore(phenotype, options, STRENGTH, MAXIMUM_ATTRIBUTE_SCORE + 1);
+ assertEquals(attributeCap, attributes.getAttributeScore(STRENGTH));
- attributes.setStrength(MINIMUM_ATTRIBUTE_SCORE - 1);
- assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getStrength());
+ attributes.setAttributeScore(phenotype, options, STRENGTH, MINIMUM_ATTRIBUTE_SCORE - 1);
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(STRENGTH));
for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
- attributes.setStrength(i);
- assertEquals(i, attributes.getStrength());
+ attributes.setAttributeScore(phenotype, options, STRENGTH, i);
+ int expected = min(i, attributeCap);
+ assertEquals(expected, attributes.getAttributeScore(STRENGTH));
}
}
@Test
public void testSetBody() {
- Attributes attributes = new Attributes();
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
+
+ final int attributeCap = phenotype.getAttributeCap(BODY);
- attributes.setBody(MAXIMUM_ATTRIBUTE_SCORE + 1);
- assertEquals(MAXIMUM_ATTRIBUTE_SCORE, attributes.getBody());
+ attributes.setAttributeScore(phenotype, options, BODY, MAXIMUM_ATTRIBUTE_SCORE + 1);
+ assertEquals(attributeCap, attributes.getAttributeScore(BODY));
- attributes.setBody(MINIMUM_ATTRIBUTE_SCORE - 1);
- assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getBody());
+ attributes.setAttributeScore(phenotype, options, BODY, MINIMUM_ATTRIBUTE_SCORE - 1);
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(BODY));
for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
- attributes.setBody(i);
- assertEquals(i, attributes.getBody());
+ attributes.setAttributeScore(phenotype, options, BODY, i);
+ int expected = min(i, attributeCap);
+ assertEquals(expected, attributes.getAttributeScore(BODY));
}
}
@Test
public void testSetReflexes() {
- Attributes attributes = new Attributes();
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
+
+ final int attributeCap = phenotype.getAttributeCap(REFLEXES);
- attributes.setReflexes(MAXIMUM_ATTRIBUTE_SCORE + 1);
- assertEquals(MAXIMUM_ATTRIBUTE_SCORE, attributes.getReflexes());
+ attributes.setAttributeScore(phenotype, options, REFLEXES, MAXIMUM_ATTRIBUTE_SCORE + 1);
+ assertEquals(attributeCap, attributes.getAttributeScore(REFLEXES));
- attributes.setReflexes(MINIMUM_ATTRIBUTE_SCORE - 1);
- assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getReflexes());
+ attributes.setAttributeScore(phenotype, options, REFLEXES, MINIMUM_ATTRIBUTE_SCORE - 1);
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(REFLEXES));
for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
- attributes.setReflexes(i);
- assertEquals(i, attributes.getReflexes());
+ attributes.setAttributeScore(phenotype, options, REFLEXES, i);
+ int expected = min(i, attributeCap);
+ assertEquals(expected, attributes.getAttributeScore(REFLEXES));
}
}
@Test
public void testSetDexterity() {
- Attributes attributes = new Attributes();
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
- attributes.setDexterity(MAXIMUM_ATTRIBUTE_SCORE + 1);
- assertEquals(MAXIMUM_ATTRIBUTE_SCORE, attributes.getDexterity());
+ final int attributeCap = phenotype.getAttributeCap(DEXTERITY);
- attributes.setDexterity(MINIMUM_ATTRIBUTE_SCORE - 1);
- assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getDexterity());
+ attributes.setAttributeScore(phenotype, options, DEXTERITY, MAXIMUM_ATTRIBUTE_SCORE + 1);
+ assertEquals(attributeCap, attributes.getAttributeScore(DEXTERITY));
+
+ attributes.setAttributeScore(phenotype, options, DEXTERITY, MINIMUM_ATTRIBUTE_SCORE - 1);
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(DEXTERITY));
for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
- attributes.setDexterity(i);
- assertEquals(i, attributes.getDexterity());
+ attributes.setAttributeScore(phenotype, options, DEXTERITY, i);
+ int expected = min(i, attributeCap);
+ assertEquals(expected, attributes.getAttributeScore(DEXTERITY));
}
}
@Test
public void testSetIntelligence() {
- Attributes attributes = new Attributes();
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
- attributes.setIntelligence(MAXIMUM_ATTRIBUTE_SCORE + 1);
- assertEquals(MAXIMUM_ATTRIBUTE_SCORE, attributes.getIntelligence());
+ final int attributeCap = phenotype.getAttributeCap(INTELLIGENCE);
- attributes.setIntelligence(MINIMUM_ATTRIBUTE_SCORE - 1);
- assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getIntelligence());
+ attributes.setAttributeScore(phenotype, options, INTELLIGENCE, MAXIMUM_ATTRIBUTE_SCORE + 1);
+ assertEquals(attributeCap, attributes.getAttributeScore(INTELLIGENCE));
+
+ attributes.setAttributeScore(phenotype, options, INTELLIGENCE, MINIMUM_ATTRIBUTE_SCORE - 1);
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(INTELLIGENCE));
for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
- attributes.setIntelligence(i);
- assertEquals(i, attributes.getIntelligence());
+ attributes.setAttributeScore(phenotype, options, INTELLIGENCE, i);
+ int expected = min(i, attributeCap);
+ assertEquals(expected, attributes.getAttributeScore(INTELLIGENCE));
}
}
@Test
public void testSetWillpower() {
- Attributes attributes = new Attributes();
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
- attributes.setWillpower(MAXIMUM_ATTRIBUTE_SCORE + 1);
- assertEquals(MAXIMUM_ATTRIBUTE_SCORE, attributes.getWillpower());
+ final int attributeCap = phenotype.getAttributeCap(WILLPOWER);
- attributes.setWillpower(MINIMUM_ATTRIBUTE_SCORE - 1);
- assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getWillpower());
+ attributes.setAttributeScore(phenotype, options, WILLPOWER, MAXIMUM_ATTRIBUTE_SCORE + 1);
+ assertEquals(phenotype.getAttributeCap(WILLPOWER), attributes.getAttributeScore(WILLPOWER));
+
+ attributes.setAttributeScore(phenotype, options, WILLPOWER, MINIMUM_ATTRIBUTE_SCORE - 1);
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(WILLPOWER));
for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
- attributes.setWillpower(i);
- assertEquals(i, attributes.getWillpower());
+ attributes.setAttributeScore(phenotype, options, WILLPOWER, i);
+ int expected = min(i, attributeCap);
+ assertEquals(expected, attributes.getAttributeScore(WILLPOWER));
}
}
@Test
public void testSetCharisma() {
- Attributes attributes = new Attributes();
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
+
+ final int attributeCap = phenotype.getAttributeCap(CHARISMA);
- attributes.setCharisma(MAXIMUM_ATTRIBUTE_SCORE + 1);
- assertEquals(MAXIMUM_ATTRIBUTE_SCORE, attributes.getCharisma());
+ attributes.setAttributeScore(phenotype, options, CHARISMA, MAXIMUM_ATTRIBUTE_SCORE + 1);
+ assertEquals(phenotype.getAttributeCap(CHARISMA), attributes.getAttributeScore(CHARISMA));
- attributes.setCharisma(MINIMUM_ATTRIBUTE_SCORE - 1);
- assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getCharisma());
+ attributes.setAttributeScore(phenotype, options, CHARISMA, MINIMUM_ATTRIBUTE_SCORE - 1);
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(CHARISMA));
for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
- attributes.setCharisma(i);
- assertEquals(i, attributes.getCharisma());
+ attributes.setAttributeScore(phenotype, options, CHARISMA, i);
+ assertEquals(min(i, phenotype.getAttributeCap(CHARISMA)), attributes.getAttributeScore(CHARISMA));
}
}
@Test
public void testChangeAllAttributes_BelowMinimum() {
- Attributes attributes = new Attributes();
- attributes.changeAllAttributes(-999);
- assertEqualsAllAttributes(MINIMUM_ATTRIBUTE_SCORE, attributes);
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
+
+ attributes.changeAllAttributes(phenotype, options, -999);
+
+ for (SkillAttribute attribute : SkillAttribute.values()) {
+ if (attribute.isNone()) {
+ continue;
+ }
+
+ assertEquals(MINIMUM_ATTRIBUTE_SCORE, attributes.getAttributeScore(attribute));
+ }
}
@Test
public void testChangeAllAttributes_AboveMaximum() {
- Attributes attributes = new Attributes();
- attributes.changeAllAttributes(999);
- assertEqualsAllAttributes(MAXIMUM_ATTRIBUTE_SCORE, attributes);
- }
+ final Attributes attributes = new Attributes();
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
- @Test
- public void testChangeAllAttributes_AllPossibleValues() {
- int minimum = MINIMUM_ATTRIBUTE_SCORE - DEFAULT_ATTRIBUTE_SCORE;
- int maximum = MAXIMUM_ATTRIBUTE_SCORE - DEFAULT_ATTRIBUTE_SCORE;
+ attributes.changeAllAttributes(phenotype, options, 999);
- for (int i = minimum; i <= maximum; i++) {
- Attributes attributes = new Attributes();
- int expectation = DEFAULT_ATTRIBUTE_SCORE + i;
+ for (SkillAttribute attribute : SkillAttribute.values()) {
+ if (attribute.isNone()) {
+ continue;
+ }
- attributes.changeAllAttributes(i);
- assertEqualsAllAttributes(expectation, attributes);
+ assertEquals(phenotype.getAttributeCap(attribute), attributes.getAttributeScore(attribute));
}
}
- /**
- * Asserts that all attributes of the given {@link Attributes} object are equal to the expected value.
- *
- *
This utility method performs assertions on the following attributes:
- *
- *
Strength
- *
Body
- *
Reflexes
- *
Dexterity
- *
Intelligence
- *
Willpower
- *
Charisma
- *
- *
If any attribute does not match the expected value, an assertion error will be thrown.
- *
- * @param expectation the expected value for all attributes.
- * @param attributes the {@link Attributes} object whose attributes are being tested.
- *
- * @throws AssertionError if any attribute does not match the expected value.
- * @since 0.50.5
- */
- private static void assertEqualsAllAttributes(int expectation, Attributes attributes) {
- assertEquals(expectation, attributes.getStrength());
- assertEquals(expectation, attributes.getBody());
- assertEquals(expectation, attributes.getReflexes());
- assertEquals(expectation, attributes.getDexterity());
- assertEquals(expectation, attributes.getIntelligence());
- assertEquals(expectation, attributes.getWillpower());
- assertEquals(expectation, attributes.getCharisma());
+ @Test
+ public void testChangeAllAttributes_AllPossibleValues() {
+ final Phenotype phenotype = Phenotype.GENERAL;
+ final PersonnelOptions options = new PersonnelOptions();
+
+ for (int i = MINIMUM_ATTRIBUTE_SCORE; i <= MAXIMUM_ATTRIBUTE_SCORE; i++) {
+ // reset attributes
+ Attributes attributes = new Attributes(MINIMUM_ATTRIBUTE_SCORE);
+
+ attributes.changeAllAttributes(phenotype, options, i);
+
+ for (SkillAttribute attribute : SkillAttribute.values()) {
+ if (attribute.isNone()) {
+ continue;
+ }
+
+ int newValue = attributes.getAttributeScore(attribute);
+ int expected = MINIMUM_ATTRIBUTE_SCORE + i;
+ // Account for attribute caps
+ expected = min(expected, phenotype.getAttributeCap(attribute));
+ assertEquals(expected, newValue);
+ }
+ }
}
}
diff --git a/MekHQ/unittests/mekhq/gui/enums/PersonnelTableModelColumnTest.java b/MekHQ/unittests/mekhq/gui/enums/PersonnelTableModelColumnTest.java
index 4c1a2181ace..223e5c5f0ec 100644
--- a/MekHQ/unittests/mekhq/gui/enums/PersonnelTableModelColumnTest.java
+++ b/MekHQ/unittests/mekhq/gui/enums/PersonnelTableModelColumnTest.java
@@ -41,6 +41,7 @@
import megamek.common.util.sorter.NaturalOrderComparator;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
+import mekhq.gui.sorter.AttributeScoreSorter;
import mekhq.gui.sorter.BonusSorter;
import mekhq.gui.sorter.DateStringComparator;
import mekhq.gui.sorter.FormattedNumberSorter;
@@ -848,77 +849,58 @@ public void testGetComparator() {
final Campaign mockCampaign = mock(Campaign.class);
for (final PersonnelTableModelColumn personnelTableModelColumn : columns) {
switch (personnelTableModelColumn) {
- case RANK:
- assertInstanceOf(PersonRankStringSorter.class,
- personnelTableModelColumn.getComparator(mockCampaign));
- break;
- case AGE:
- case BIRTHDAY:
- case RECRUITMENT_DATE:
- case LAST_RANK_CHANGE_DATE:
- case DUE_DATE:
- case RETIREMENT_DATE:
- case DEATH_DATE:
- assertInstanceOf(DateStringComparator.class, personnelTableModelColumn.getComparator(mockCampaign));
- break;
- case SKILL_LEVEL:
- assertInstanceOf(LevelSorter.class, personnelTableModelColumn.getComparator(mockCampaign));
- break;
- case MEK:
- case GROUND_VEHICLE:
- case NAVAL_VEHICLE:
- case VTOL:
- case AEROSPACE:
- case CONVENTIONAL_AIRCRAFT:
- case VESSEL:
- case BATTLE_ARMOUR:
- case SMALL_ARMS:
- case ANTI_MEK:
- case ARTILLERY:
- case TACTICS:
- case STRATEGY:
- case LEADERSHIP:
- case TECH_MEK:
- case TECH_AERO:
- case TECH_MECHANIC:
- case TECH_BA:
- case TECH_VESSEL:
- case MEDICAL:
- case ADMINISTRATION:
- case NEGOTIATION:
- case SCROUNGE:
- assertInstanceOf(BonusSorter.class, personnelTableModelColumn.getComparator(mockCampaign));
- break;
- case INJURIES:
- case KILLS:
- case XP:
- case TOUGHNESS:
- case CONNECTIONS:
- case WEALTH:
- case REPUTATION:
- case UNLUCKY:
- case EDGE:
- case SPA_COUNT:
- case IMPLANT_COUNT:
- case LOYALTY:
- case REASONING:
- case STRENGTH:
- case BODY:
- case REFLEXES:
- case DEXTERITY:
- case INTELLIGENCE:
- case WILLPOWER:
- case CHARISMA:
- assertInstanceOf(IntegerStringSorter.class, personnelTableModelColumn.getComparator(mockCampaign));
- break;
- case SALARY:
- assertInstanceOf(FormattedNumberSorter.class,
- personnelTableModelColumn.getComparator(mockCampaign));
- break;
- default:
- assertInstanceOf(NaturalOrderComparator.class,
- personnelTableModelColumn.getComparator(mockCampaign));
- break;
+ case RANK -> assertInstanceOf(PersonRankStringSorter.class,
+ personnelTableModelColumn.getComparator(mockCampaign));
+ case AGE, BIRTHDAY, RECRUITMENT_DATE, LAST_RANK_CHANGE_DATE, DUE_DATE, RETIREMENT_DATE, DEATH_DATE ->
+ assertInstanceOf(DateStringComparator.class,
+ personnelTableModelColumn.getComparator(mockCampaign));
+ case SKILL_LEVEL ->
+ assertInstanceOf(LevelSorter.class, personnelTableModelColumn.getComparator(mockCampaign));
+ case MEK,
+ GROUND_VEHICLE,
+ NAVAL_VEHICLE,
+ VTOL,
+ AEROSPACE,
+ CONVENTIONAL_AIRCRAFT,
+ VESSEL,
+ BATTLE_ARMOUR,
+ SMALL_ARMS,
+ ANTI_MEK,
+ ARTILLERY,
+ TACTICS,
+ STRATEGY,
+ LEADERSHIP,
+ TECH_MEK,
+ TECH_AERO,
+ TECH_MECHANIC,
+ TECH_BA,
+ TECH_VESSEL,
+ MEDICAL,
+ ADMINISTRATION,
+ NEGOTIATION,
+ SCROUNGE ->
+ assertInstanceOf(BonusSorter.class, personnelTableModelColumn.getComparator(mockCampaign));
+ case INJURIES,
+ KILLS,
+ XP,
+ TOUGHNESS,
+ CONNECTIONS,
+ WEALTH,
+ REPUTATION,
+ UNLUCKY,
+ EDGE,
+ SPA_COUNT,
+ IMPLANT_COUNT,
+ LOYALTY,
+ REASONING -> assertInstanceOf(IntegerStringSorter.class,
+ personnelTableModelColumn.getComparator(mockCampaign));
+ case STRENGTH, BODY, REFLEXES, DEXTERITY, INTELLIGENCE, WILLPOWER, CHARISMA -> assertInstanceOf(
+ AttributeScoreSorter.class,
+ personnelTableModelColumn.getComparator(mockCampaign));
+ case SALARY -> assertInstanceOf(FormattedNumberSorter.class,
+ personnelTableModelColumn.getComparator(mockCampaign));
+ default -> assertInstanceOf(NaturalOrderComparator.class,
+ personnelTableModelColumn.getComparator(mockCampaign));
}
}
}
From f62c51000b4002d8e3314ab4adbe7edc57d08c55 Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Fri, 11 Apr 2025 19:38:56 -0500
Subject: [PATCH 09/10] - Updated `getAttributeScore` logic in `Person.java` to
account for SPAs.
---
.../src/mekhq/campaign/personnel/Person.java | 38 ++++++++++++++++++-
.../campaign/personnel/skills/Attributes.java | 1 +
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java
index 3cf70db31b5..bb064c22040 100644
--- a/MekHQ/src/mekhq/campaign/personnel/Person.java
+++ b/MekHQ/src/mekhq/campaign/personnel/Person.java
@@ -5235,7 +5235,43 @@ public int getAttributeScore(final SkillAttribute attribute) {
return DEFAULT_ATTRIBUTE_SCORE;
}
- return atowAttributes.getAttributeScore(attribute);
+ boolean hasFreakishStrength = options.booleanOption(MUTATION_FREAKISH_STRENGTH);
+ boolean hasExoticAppearance = options.booleanOption(MUTATION_EXOTIC_APPEARANCE);
+ boolean hasFacialHair = options.booleanOption(MUTATION_FACIAL_HAIR);
+ boolean hasSeriousDisfigurement = options.booleanOption(MUTATION_SERIOUS_DISFIGUREMENT);
+ boolean isCatGirl = options.booleanOption(MUTATION_CAT_GIRL);
+ boolean isCatGirlUnofficial = options.booleanOption(MUTATION_CAT_GIRL_UNOFFICIAL);
+
+ return switch (attribute) {
+ case NONE -> 0;
+ case STRENGTH -> {
+ int attributeScore = atowAttributes.getAttributeScore(attribute);
+ if (hasFreakishStrength) {
+ attributeScore += 2;
+ }
+ yield min(attributeScore, MAXIMUM_ATTRIBUTE_SCORE);
+ }
+ case BODY, REFLEXES, DEXTERITY, INTELLIGENCE, WILLPOWER -> atowAttributes.getAttributeScore(attribute);
+ case CHARISMA -> {
+ int attributeScore = atowAttributes.getAttributeScore(attribute);
+ if (hasExoticAppearance) {
+ attributeScore++;
+ }
+ if (hasFacialHair) {
+ attributeScore--;
+ }
+ if (hasSeriousDisfigurement) {
+ attributeScore -= 3;
+ }
+ if (isCatGirl) {
+ attributeScore -= 3;
+ }
+ if (isCatGirlUnofficial) {
+ attributeScore++;
+ }
+ yield clamp(attributeScore, MINIMUM_ATTRIBUTE_SCORE, MAXIMUM_ATTRIBUTE_SCORE);
+ }
+ };
}
/**
diff --git a/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java b/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
index 7bb56f99bce..2eba96e587e 100644
--- a/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
+++ b/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
@@ -35,6 +35,7 @@
import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_REFLEXES;
import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_STRENGTH;
import static mekhq.campaign.personnel.PersonnelOptions.EXCEPTIONAL_ATTRIBUTE_WILLPOWER;
+import static mekhq.campaign.personnel.PersonnelOptions.MUTATION_FREAKISH_STRENGTH;
import java.io.PrintWriter;
From 95732d39b1ddacde6f2e0133d6e141ee5d5d514c Mon Sep 17 00:00:00 2001
From: IllianiCBT
Date: Fri, 11 Apr 2025 19:41:04 -0500
Subject: [PATCH 10/10] - Fixed javadocs
---
.../campaign/personnel/skills/Attributes.java | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java b/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
index 2eba96e587e..f51f1627e82 100644
--- a/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
+++ b/MekHQ/src/mekhq/campaign/personnel/skills/Attributes.java
@@ -352,7 +352,7 @@ public int getStrength() {
}
/**
- * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
+ * @deprecated use {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} instead.
*/
@Deprecated(since = "0.50.5", forRemoval = true)
public void setStrength(int strength) {
@@ -368,7 +368,7 @@ public int getBody() {
}
/**
- * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
+ * @deprecated use {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} instead.
*/
@Deprecated(since = "0.50.5", forRemoval = true)
public void setBody(int body) {
@@ -384,7 +384,7 @@ public int getReflexes() {
}
/**
- * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
+ * @deprecated use {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} instead.
*/
@Deprecated(since = "0.50.5", forRemoval = true)
public void setReflexes(int reflexes) {
@@ -400,7 +400,7 @@ public int getDexterity() {
}
/**
- * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
+ * @deprecated use {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} instead.
*/
@Deprecated(since = "0.50.5", forRemoval = true)
public void setDexterity(int dexterity) {
@@ -416,7 +416,7 @@ public int getIntelligence() {
}
/**
- * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
+ * @deprecated use {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} instead.
*/
@Deprecated(since = "0.50.5", forRemoval = true)
public void setIntelligence(int intelligence) {
@@ -432,7 +432,7 @@ public int getWillpower() {
}
/**
- * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
+ * @deprecated use {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} instead.
*/
@Deprecated(since = "0.50.5", forRemoval = true)
public void setWillpower(int willpower) {
@@ -448,7 +448,7 @@ public int getCharisma() {
}
/**
- * @deprecated use {@link #setAttributeScore(SkillAttribute, int)} instead.
+ * @deprecated use {@link #setAttributeScore(Phenotype, PersonnelOptions, SkillAttribute, int)} instead.
*/
@Deprecated(since = "0.50.5", forRemoval = true)
public void setCharisma(int charisma) {