From 15d3fc7a8aa3f8541e8f4568eef59f69ed2dff64 Mon Sep 17 00:00:00 2001 From: IllianiBird Date: Sun, 17 May 2026 20:00:57 -0500 Subject: [PATCH 1/2] Made Attribute Score Modifiers Clear in Personnel Table --- .../src/mekhq/campaign/personnel/Person.java | 22 ++++++++ .../gui/enums/PersonnelTableModelColumn.java | 51 +++++++++++-------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java index 4eaece194f7..f8aee817b73 100644 --- a/MekHQ/src/mekhq/campaign/personnel/Person.java +++ b/MekHQ/src/mekhq/campaign/personnel/Person.java @@ -7057,6 +7057,28 @@ public int getAttributeCap(final SkillAttribute attribute) { return atowAttributes.getAttributeCap(phenotype, options, attribute); } + /** + * Retrieves the modifier value for a specified skill attribute. + * + * @param attribute the skill attribute for which the modifier is to be calculated; + * if the attribute is null or represents "none", a warning is logged and the method returns 0 + * @return the calculated modifier value for the provided skill attribute, or 0 if the attribute is null or "none" + * + * @author Illiani + * @since 0.51.00 + */ + public int getAttributeModifier(final SkillAttribute attribute) { + if (attribute == null || attribute.isNone()) { + LOGGER.warn("(getAttributeModifier) SkillAttribute is null or NONE."); + return 0; + } + + return atowAttributes.getAttributeModifier(attribute, + getActiveInjuryEffects(), + options, + ageForAttributeModifiers); + } + /** * Sets the character's {@link Attributes} object which contains their ATOW Attribute scores. * diff --git a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java index 6459b9174be..3be741430cf 100644 --- a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java +++ b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java @@ -85,6 +85,7 @@ import mekhq.gui.sorter.PersonRankStringSorter; import mekhq.gui.sorter.ReasoningSorter; import mekhq.utilities.ReportingUtilities; +import org.jspecify.annotations.NonNull; public enum PersonnelTableModelColumn { // region Enum Declarations @@ -622,6 +623,7 @@ public String getCellValue(final Campaign campaign, final PersonnelMarket person // We define these here, as they're used in multiple cases int currentAttributeValue; int attributeCap; + int attributeModifier; String sign; @@ -1122,33 +1124,19 @@ public String getCellValue(final Campaign campaign, final PersonnelMarket person Reasoning reasoning = person.getReasoning(); return reasoning.getLabel(); case STRENGTH: - currentAttributeValue = person.getAttributeScore(SkillAttribute.STRENGTH); - attributeCap = person.getAttributeCap(SkillAttribute.STRENGTH); - return currentAttributeValue + " / " + attributeCap; + return getAttributeScoreDisplay(person, SkillAttribute.STRENGTH); case BODY: - currentAttributeValue = person.getAttributeScore(SkillAttribute.BODY); - attributeCap = person.getAttributeCap(SkillAttribute.BODY); - return currentAttributeValue + " / " + attributeCap; + return getAttributeScoreDisplay(person, SkillAttribute.BODY); case REFLEXES: - currentAttributeValue = person.getAttributeScore(SkillAttribute.REFLEXES); - attributeCap = person.getAttributeCap(SkillAttribute.REFLEXES); - return currentAttributeValue + " / " + attributeCap; + return getAttributeScoreDisplay(person, SkillAttribute.REFLEXES); case DEXTERITY: - currentAttributeValue = person.getAttributeScore(SkillAttribute.DEXTERITY); - attributeCap = person.getAttributeCap(SkillAttribute.DEXTERITY); - return currentAttributeValue + " / " + attributeCap; + return getAttributeScoreDisplay(person, SkillAttribute.DEXTERITY); case INTELLIGENCE: - currentAttributeValue = person.getAttributeScore(SkillAttribute.INTELLIGENCE); - attributeCap = person.getAttributeCap(SkillAttribute.INTELLIGENCE); - return currentAttributeValue + " / " + attributeCap; + return getAttributeScoreDisplay(person, SkillAttribute.INTELLIGENCE); case WILLPOWER: - currentAttributeValue = person.getAttributeScore(SkillAttribute.WILLPOWER); - attributeCap = person.getAttributeCap(SkillAttribute.WILLPOWER); - return currentAttributeValue + " / " + attributeCap; + return getAttributeScoreDisplay(person, SkillAttribute.WILLPOWER); case CHARISMA: - currentAttributeValue = person.getAttributeScore(SkillAttribute.CHARISMA); - attributeCap = person.getAttributeCap(SkillAttribute.CHARISMA); - return currentAttributeValue + " / " + attributeCap; + return getAttributeScoreDisplay(person, SkillAttribute.CHARISMA); case EDGE: currentAttributeValue = person.getAttributeScore(SkillAttribute.EDGE); attributeCap = person.getAttributeCap(SkillAttribute.EDGE); @@ -1158,6 +1146,27 @@ public String getCellValue(final Campaign campaign, final PersonnelMarket person } } + /** + * Constructs a displayable string representation of a person's skill attribute, including their current score, + * maximum possible score (cap), and attribute modifier. + * + * @param person the person whose attribute scores are being represented + * @param attribute the specific skill attribute being evaluated + * @return a string in the format "currentScore / attributeCap (+/- modifier)" + * + * @author Illiani + * @since 0.51.00 + */ + private static @NonNull String getAttributeScoreDisplay(Person person, SkillAttribute attribute) { + int currentAttributeValue = person.getAttributeScore(attribute); + int attributeCap = person.getAttributeCap(attribute); + + int attributeModifier = person.getAttributeModifier(attribute); + String sign = attributeModifier >= 0 ? "+" : ""; + + return currentAttributeValue + " / " + attributeCap + " (" + sign + attributeModifier + ")"; + } + public @Nullable String getDisplayText(final Campaign campaign, final Person person) { if (this == PersonnelTableModelColumn.AGE) { return Integer.toString(person.getAge(campaign.getLocalDate())); From 7d58dfd95c9b5d33993b8d413adecf304455c542 Mon Sep 17 00:00:00 2001 From: IllianiBird Date: Mon, 18 May 2026 11:01:45 -0500 Subject: [PATCH 2/2] Fixed stale caching --- MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java index 3be741430cf..aa926361fe2 100644 --- a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java +++ b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java @@ -620,11 +620,6 @@ public boolean isPersonality() { public String getCellValue(final Campaign campaign, final PersonnelMarket personnelMarket, final Person person, final boolean loadAssignmentFromMarket, final boolean groupByUnit) { - // We define these here, as they're used in multiple cases - int currentAttributeValue; - int attributeCap; - int attributeModifier; - String sign; final boolean isClanCampaign = campaign.isClanCampaign(); @@ -1138,8 +1133,8 @@ public String getCellValue(final Campaign campaign, final PersonnelMarket person case CHARISMA: return getAttributeScoreDisplay(person, SkillAttribute.CHARISMA); case EDGE: - currentAttributeValue = person.getAttributeScore(SkillAttribute.EDGE); - attributeCap = person.getAttributeCap(SkillAttribute.EDGE); + int currentAttributeValue = person.getAttributeScore(SkillAttribute.EDGE); + int attributeCap = person.getAttributeCap(SkillAttribute.EDGE); return currentAttributeValue + " / " + attributeCap; default: return "UNIMPLEMENTED";