From abe72c01e907d01be44313ec28c73740f4215fc4 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Thu, 9 Jan 2025 14:42:52 -0600 Subject: [PATCH] Handle routed payouts for routed AtB contracts Added support for calculating and storing routed payouts when AtB contracts end due to the enemy being routed. Updated XML serialization and deserialization to include routed payout data. This ensures accurate financial tracking for such contract conclusions. --- MekHQ/src/mekhq/campaign/Campaign.java | 11 ++++++++--- .../mekhq/campaign/mission/AtBContract.java | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index dfa601762f..d990d83f57 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -7802,10 +7802,15 @@ public void completeMission(@Nullable Mission mission, MissionStatus status) { // check for money in escrow // According to FMM(r) pg 179, both failure and breach lead to no // further payment even though this seems foolish - if ((contract.getStatus().isSuccess()) - && (contract.getMonthsLeft(getLocalDate()) > 0)) { + if (contract.getStatus().isSuccess()) { remainingMoney = contract.getMonthlyPayOut() - .multipliedBy(contract.getMonthsLeft(getLocalDate())); + .multipliedBy(contract.getMonthsLeft(getLocalDate())); + + if (contract instanceof AtBContract) { + Money routedPayout = ((AtBContract) contract).getRoutedPayout(); + + remainingMoney = routedPayout == null ? remainingMoney : routedPayout; + } } // If overage repayment is enabled, we first need to check if the salvage diff --git a/MekHQ/src/mekhq/campaign/mission/AtBContract.java b/MekHQ/src/mekhq/campaign/mission/AtBContract.java index ac53e14986..ce6d056ee8 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBContract.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBContract.java @@ -30,6 +30,7 @@ import megamek.common.Entity; import megamek.common.TargetRoll; import megamek.common.UnitType; +import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; import megamek.common.enums.SkillLevel; import megamek.common.icons.Camouflage; @@ -162,6 +163,7 @@ public class AtBContract extends Contract { protected int contractScoreArbitraryModifier; protected int moraleMod = 0; + private Money routedPayout = null; /* lasts for a month, then removed at next events roll */ protected boolean priorLogisticsFailure; @@ -619,8 +621,10 @@ public void checkMorale(Campaign campaign, LocalDate today) { if (contractType.isGarrisonType() && !contractType.isRiotDuty()) { routEnd = today.plusMonths(max(1, d6() - 3)).minusDays(1); } else { - campaign.addReport("With the enemy routed, any remaining objectives have been successfully completed." + - " The contract will conclude tomorrow."); + campaign.addReport("With the enemy routed, any remaining objectives have been" + + " successfully completed. The contract will conclude tomorrow."); + int remainingMonths = getMonthsLeft(campaign.getLocalDate().plusDays(1)); + routedPayout = getMonthlyPayOut().multipliedBy(remainingMonths); setEndDate(today.plusDays(1)); } } @@ -1134,6 +1138,9 @@ protected int writeToXMLBegin(final PrintWriter pw, int indent) { if (routEnd != null) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "routEnd", routEnd); } + if (routedPayout != null) { + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "routedPayout", routedPayout); + } MHQXMLUtility.writeSimpleXMLTag(pw, indent, "partsAvailabilityLevel", getPartsAvailabilityLevel()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "extensionLength", extensionLength); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "sharesPct", sharesPct); @@ -1210,6 +1217,9 @@ public void loadFieldsFromXmlNode(Node wn) throws ParseException { setMoraleLevel(AtBMoraleLevel.parseFromString(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("routEnd")) { routEnd = MHQXMLUtility.parseDate(wn2.getTextContent().trim()); + } else if (wn2.getNodeName().equalsIgnoreCase("routedPayout")) { + double value = Double.parseDouble(wn2.getTextContent().trim()); + routedPayout = Money.of(value); } else if (wn2.getNodeName().equalsIgnoreCase("partsAvailabilityLevel")) { partsAvailabilityLevel = Integer.parseInt(wn2.getTextContent()); } else if (wn2.getNodeName().equalsIgnoreCase("extensionLength")) { @@ -2158,4 +2168,8 @@ public int getTransportRoll() { public void setTransportRoll(int roll) { transportRoll = roll; } + + public @Nullable Money getRoutedPayout() { + return routedPayout; + } }