Improvement: Added Contract Pay Diminishing Returns Campaign Option#8522
Improvement: Added Contract Pay Diminishing Returns Campaign Option#8522IllianiBird merged 12 commits intoMegaMek:mainfrom
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #8522 +/- ##
============================================
+ Coverage 12.39% 12.43% +0.03%
- Complexity 7474 7493 +19
============================================
Files 1290 1290
Lines 165569 165620 +51
Branches 24924 24942 +18
============================================
+ Hits 20526 20587 +61
+ Misses 143084 143069 -15
- Partials 1959 1964 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a diminishing returns system for contract pay calculations to address the issue of infinite campaign growth in MekHQ. The feature works in conjunction with the alternate payment model to create a soft cap on campaign size by progressively reducing the marginal value of units beyond two battalions (or factional equivalent).
Key Changes:
- Adds a new diminishing returns calculation that reduces unit values for contract pay once combat forces exceed two battalions, capping at 10% value around four battalions
- Integrates diminishing returns with both the new alternate payment model and existing equipment-based contract pay systems
- Introduces user-facing confirmation dialogs to warn players about the economic impact when enabling these options mid-campaign
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
AlternatePaymentModelValues.java |
Core implementation of diminishing returns calculation with configurable slope, power, and floor values; also includes the alternate payment model unit valuation system |
AlternatePaymentModelValuesTest.java |
Comprehensive test coverage for diminishing returns logic, including edge cases, formula verification, and sorting behavior |
Accountant.java |
Integration of diminishing returns into contract base pay calculation for all relevant payment models |
Force.java |
New getUnitsAsUnits(Hangar) convenience method to resolve unit IDs to Unit objects |
CampaignOptions.java |
Adds useAlternatePaymentMode and useDiminishingContractPay boolean options |
CampaignOptionsFreebieTracker.java |
Tracks changes to the new options to trigger appropriate dialogs when enabled |
CampaignOptionsMarshaller.java |
XML serialization support for the new campaign options |
CampaignOptionsUnmarshaller.java |
XML deserialization support for the new campaign options |
CampaignOptionsPane.java |
Triggers confirmation dialogs when players enable the new options in existing campaigns |
CampaignUpgradeDialog.java |
Reorders option tracking to occur after options are fully applied during campaign upgrades |
MarketsTab.java |
Adds UI checkboxes for the two new campaign options in the Markets tab |
NormalizedContractPayCampaignOptionsChangedConfirmationDialog.java |
User-facing dialog warning about potential contract pay reduction when enabling alternate payment mode |
DiminishingReturnsCampaignOptionsChangedConfirmationDialog.java |
User-facing dialog explaining diminishing returns when enabling the option |
*.properties files |
Localization strings for tooltips, dialog messages, and UI labels |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
MekHQ/src/mekhq/campaign/campaignOptions/CampaignOptionsFreebieTracker.java
Outdated
Show resolved
Hide resolved
MekHQ/src/mekhq/campaign/market/contractMarket/AlternatePaymentModelValues.java
Outdated
Show resolved
Hide resolved
...ources/mekhq/resources/DiminishingReturnsCampaignOptionsChangedConfirmationDialog.properties
Outdated
Show resolved
Hide resolved
MekHQ/src/mekhq/campaign/campaignOptions/CampaignOptionsFreebieTracker.java
Outdated
Show resolved
Hide resolved
…eTracker.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tModelValues.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…onsChangedConfirmationDialog.properties Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
# Conflicts: # MekHQ/src/mekhq/campaign/market/contractMarket/AlternatePaymentModelValues.java # MekHQ/unittests/mekhq/campaign/market/contractMarket/AlternatePaymentModelValuesTest.java
| NormalizedContractPayCampaignOptionsChangedConfirmationDialog.message=<h1 style="text-align:center">Normalized \ | ||
| Contract Pay</h1>\ | ||
| You have just enabled normalized contract pay in a campaign that previously had it disabled. This option was \ | ||
| introduced as a method to make things easier for new campaigns with poor equipment. It was also implemented to \ | ||
| reduce the issue of growth spirals in late game campaigns.\ | ||
| <p>This option significantly changes how contract base pay is calculated. It places the emphasis on the types of \ | ||
| unit in your TO&E, rather than each unit's value. If you are familiar with Generic Battle Value, normalized \ | ||
| contract pay works in a similar (though not identical) manner.</p>\ | ||
| <p>As you are enabling this option in an ongoing campaign, you must be prepared for a potentially massive reduction \ | ||
| in contract pay. Depending on the units in your roster, and your other campaign options, it is entirely possible \ | ||
| that your campaign may no longer be financially viable.</p>\ | ||
| <p>It is recommended that you generate a handful of contracts using GM mode to get a feel for the new pay scale. \ | ||
| You should consider disabling this option in the event your campaign is no longer playable.</p> | ||
| NormalizedContractPayCampaignOptionsChangedConfirmationDialog.button.cancel=Turn Off Normalized Contract Pay | ||
| NormalizedContractPayCampaignOptionsChangedConfirmationDialog.button.confirm=Leave Normalized Contract Pay On |
There was a problem hiding this comment.
I needed Diminishing Returns active before I could push the option change dialog confirmation for Normalized, so it made sense to merge the former into the latter
Includes Improvement: Added New Alternate Contract Payment Model
A Note for Reviewers
This PR includes all of the changes found in the above. I recommend not trying to review this PR until the above has been merged.
The Problem
The issue of infinite growth is something I've been thinking about a lot, throughout this dev cycle and the end of 50.10's. To give a brief summary, under CamOps contract pay is based on the value of the available combat units in the campaign. In this way contracts scale based on the campaign. A campaign with only a company will be paid 5% of that company's value. While a campaign consisting of an Army Group will be paid 5% of the value of the entire Army Group.
On paper this seems reasonable and allows the system to scale smoothly. However this runs into a problem we see a lot, when translating CamOps rules: the disparity between the kinds of campaigns CamOps was designed for and MekHQ.
CamOps vs. MekHQ Disparity of Design
CamOps was written with in-person campaigns in mind. Where a group of friends get together once or twice a month to play a number of connected scenarios. Growth is inherently limited by the limited length of the campaign, or at least its slow progression.
In MekHQ players can complete multiple contracts in a single evening. Growth is limited only by a players' available RAM and patience. In the past there were effective caps on campaign size, mainly in the form of poor performance and tedium. Nowadays, thanks to the improvements we've made over the past two years, we're seeing a creeping trend towards larger and larger campaigns.
In the past a battalion was 'endgame,' now a battalion is just an established campaign. Now, 'endgame' can be multiple regiments, or larger.
Exponential Growth
Finally, we run into another issue. Once a campaign reaches a certain skill threshold (be that player skill, personnel skill, or both) we start seeing decreasing loses. Without a need to replace personnel and equipment that 5% of unit value quickly becomes effectively pure profit. When combined with salvage takings the player can growth their campaign exponentially.
A Solution
Our solution to the above issues is three part:
A Growth Soft Cap
Players often ask how big they should grow their campaign, the generic answer is "stop when you want to." This PR introduces an alternative answer: "stop when you can't afford to grow any larger."
When campaign pay is calculated there is a bunch of math involved, but the most relevant is unit value. As described above we total the value of the combat units in the players' TO&E and derive base contract pay from that value.
With this PR we introduce diminishing returns on that derived value. All units up to two battalions (or factional equivalent) are valued as normal. However, all units beyond that suffer diminishing returns on their value (capped at 10% around 4 battalions). To avoid overly penalizing the player their most expensive units are counted first.
Clarification
It is important to note that diminishing returns affects the value of the unit not the unit's final contributions. By default only 5% of the unit's value is contributed to base contract pay. Therefore we reduce the unit's value by the diminishing returns and that value is the one used by the 5% calculation.