diff --git a/MekHQ/data/images/misc/MekHQ.png b/MekHQ/data/images/misc/MekHQ.png
new file mode 100644
index 0000000000..e3fe50fe9b
Binary files /dev/null and b/MekHQ/data/images/misc/MekHQ.png differ
diff --git a/MekHQ/docs/history.txt b/MekHQ/docs/history.txt
index 0b907323ad..f5c44a4e6c 100644
--- a/MekHQ/docs/history.txt
+++ b/MekHQ/docs/history.txt
@@ -91,7 +91,12 @@ MEKHQ VERSION HISTORY:
+ PR #4931: Reworked AtB Bonus Rolls, Fixed Bug in Bulk Hire
+ PR #4981: Implemented Campaign Options IIC Preset Picker #4981
+ PR #4984: Refactored Daily Personnel Processing Logic.
-+ PR #4989: Adaptation to MM #6068 Replace Manual GUI scaling with FlatLaf Scaling
++ PR #4989 #4990: Adaptation to MM #6068 Replace Manual GUI scaling with FlatLaf Scaling
++ PR #5022: Better Current Location / Travel Status
++ PR #4946: Adds Recent Promotion Modifier to Turnover System
++ Fix #5010: Makes StratCon Scenario Generation Respect Non-Combat Flag in TO&E
++ Fix #4986: Camops Paid Recrutiment Removal
++ PR #5029: Better visual distinction for GM mode / overtime toggles
+ PR #5002: Correct issues with fixed map generation #5002
+ PR #4992: Add Customization Option to Refit Dialog
+ PR #5030: Replaced autoAwards Award Ceremony Placeholder Image
@@ -104,6 +109,11 @@ MEKHQ VERSION HISTORY:
+ PR #5034: New row highlights for Personnel Table: Gone, Absent, Fatigued
+ FIX #5028: Random Camo Allocation Fixes
+ PR #5036: Corrected Scenario Modifiers for HouseOfficer units
++ PR #5040: Clarify map dimensions in scenario displays
++ PR #5042: Multiple FG3 Improvements
++ PR #5043: New names cleanup and potential bugfixes
++ PR #5046: Prevent StratCon from Pulling in Player DropShips, when Option is Disabled
++ PR #5044: Add Check for StratCon Usage in getAtBBattleChance Method
0.50.0 (2024-09-01 2000 UTC) (THIS MARKS THE START OF JAVA 17 AS THE MINIMUM REQUIRED)
+ PR #4332: CI Updates for windows build and normalizing
diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
index c0561a6fc8..c8c5d35332 100644
--- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
+++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties
@@ -982,9 +982,9 @@ chkAeroRecruitsHaveUnits.toolTipText=Aerospace pilot recruits can have fighters,
## Button Panel
btnOkay.text=Confirm
-btnSavePreset.text=Confirm and Save as Preset
+btnSavePreset.text=Save Preset
btnSavePreset.toolTipText=Confirm the changes in the dialog and save it as a Campaign Preset.
-btnLoadPreset.text=Load a Preset
+btnLoadPreset.text=Load Preset
btnLoadPreset.toolTipText=Load a Campaign Preset and apply it to the current dialog. If it is during startup, it will apply all values outside of starting planet, contract count, and game options. Otherwise, it will only apply continuous preset values outside of game options.
##end Button Panel
diff --git a/MekHQ/resources/mekhq/resources/GUI.properties b/MekHQ/resources/mekhq/resources/GUI.properties
index 7f4308ee73..ba042d173e 100644
--- a/MekHQ/resources/mekhq/resources/GUI.properties
+++ b/MekHQ/resources/mekhq/resources/GUI.properties
@@ -1323,8 +1323,6 @@ btnLoadStoryArc.text=Load a Story Arc
#### RankSystemsPane Class
### Rank System
rankSystemPanel.title=Rank System
-txtInstructionsRanks.title=Customizing Ranks
-txtInstructionsRanks.text=You can use the table here to assign ranks for your campaign. You can use one of the preset rank systems from the pull-down menu, or you can design your own by creating a custom rank system. \nYou can save a single rank system as part of the campaign, with any additional custom rank systems to be saved in the user data file instead. Any additional campaign rank systems will be deleted. \nYou can also assign custom multipliers for salary. These multipliers don't need to take into account the officer multiplier which is addressed elsewhere. \n\nWARNING: \n1) This dialog doesn't warn about the deletion of any campaign custom rank systems that aren't the selected rank system for the campaign at this time. \n2) All personnel ranks will be revalidated when this is changed, to migrate them to the proper setup for their new rank system. \n3) This dialog does not validate the data at this time, so be careful with circular logic and ensure you have a valid E0 rank (one MUST be a name like "None" or "Grunt", with "None" specifically handled in code to show as a blank string when the rank name is displayed).
lblRankSystem.text=Rank System
lblRankSystem.toolTipText=This is the standard rank system used in this campaign.
comboRankSystemType.toolTipText=This is the type of rank system selected, which is where the information about the rank system is stored.
diff --git a/MekHQ/resources/mekhq/resources/NEWCampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/NEWCampaignOptionsDialog.properties
index 837d87a1db..8ac8b3e96c 100644
--- a/MekHQ/resources/mekhq/resources/NEWCampaignOptionsDialog.properties
+++ b/MekHQ/resources/mekhq/resources/NEWCampaignOptionsDialog.properties
@@ -8,4 +8,1357 @@ presetDialogSelect.tooltip=Confirm the currently selected preset.
presetDialogCustomize.name=Customize
presetDialogCustomize.tooltip=Select a preset, then open the campaign options menu.
presetDialogCancel.name=Cancel
-presetDialogCancel.tooltip=Return to the prior screen.
\ No newline at end of file
+presetDialogCancel.tooltip=Return to the prior screen.
+
+## Campaign Options Pane
+generalPanel.title=General Information
+humanResourcesParentTab.title=Human Resources
+unitDevelopmentParentTab.title=Unit Development
+logisticsAndMaintenanceParentTab.title=Logistics
+strategicOperationsParentTab.title=Strategic Operations
+
+
+## General Tab Class
+# createGeneralTab
+lblGeneral.text=Welcome, Commander
+lblGeneralBody.text=
"Mercenary life is freedom with a price.\
+
Every contract is a choice, but every choice comes with a consequence."\
+
- Captain Rex "Ironclad" Harper, Black Fang Company
+lblName.text=Unit Name
+lblName.tooltip=PLACEHOLDER
+lblNameGenerator.text=Regenerate Name
+lblNameGenerator.tooltip=PLACEHOLDER
+lblFaction.text=Unit Faction
+lblFaction.tooltip=PLACEHOLDER
+lblReputation.text=Reputation
+lblReputation.tooltip=PLACEHOLDER
+lblManualUnitRatingModifier.text=Manual Modifier
+lblManualUnitRatingModifier.tooltip=PLACEHOLDER
+lblDate.text=Start Date
+lblDate.tooltip=PLACEHOLDER
+lblCamo.text=Unit Camouflage
+lblCamo.tooltip=PLACEHOLDER
+lblIcon.text=Unit Insignia
+lblIcon.tooltip=PLACEHOLDER
+
+## RepairAndMaintenanceTab
+repairsAndMaintenanceContentTabs.title=Maintenance & Repairs
+
+repairTab.title=Repairs
+repairTab.border="Sure, I can fix it. But next time, maybe don't play chicken with an Atlas."\
+
- Chief Tech Mara "Wrench" Kell, Black Hammer Company
+
+maintenanceTab.title=Maintenance
+maintenanceTab.border="I've yet to see a battle won by duct tape, but we've gotten pretty close."\
+
- Commander Erik Drahn, Sunder Lance
+
+# createRepairTab
+lblRepairTab.text=Repair Options
+lblRepairTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Nisl senectus neque sem maximus\
+ \ accumsan nibh curae dapibus. Asuspendisse ullamcorper aliquet aliquet pretium duis litora porttitor.\
+ \ Tristique ex per aptent cras augue mus suspendisse inceptos hac. Amet ultricies sem dui etiam justo.\
+ \ Efficitur ac nisl maecenas eu ac tincidunt. Eget felis hendrerit lacinia commodo eu natoque id\
+ \ himenaeos nibh.
+lblUseEraModsCheckBox.text=Use Era Modifiers for Repair Rolls
+lblUseEraModsCheckBox.tooltip=PLACEHOLDER
+lblAssignedTechFirstCheckBox.text=Place Assigned Technicians to the Top of the List
+lblAssignedTechFirstCheckBox.tooltip=PLACEHOLDER
+lblResetToFirstTechCheckBox.text=After Repairs Jump to the Technician at the Top of the List
+lblResetToFirstTechCheckBox.tooltip=PLACEHOLDER
+lblUseQuirksBox.text=Use Quirks
+lblUseQuirksBox.tooltip=PLACEHOLDER
+lblUseAeroSystemHitsBox.text=Damage Aero System Parts by Hits Taken
+lblUseAeroSystemHitsBox.tooltip=PLACEHOLDER
+lblUseDamageMargin.text=Damage Parts by Margin of Failure
+lblUseDamageMargin.tooltip=PLACEHOLDER
+lblDamageMargin.text=Margin
+lblDamageMargin.tooltip=PLACEHOLDER
+lblDestroyPartTarget.text=Equipment hit in battle survive on a
+lblDestroyPartTarget.tooltip=PLACEHOLDER
+
+# createMaintenanceTab
+lblMaintenanceTab.text=Maintenance Options
+lblMaintenanceTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Nisl senectus neque\
+ \ sem maximus accumsan nibh curae dapibus. Asuspendisse ullamcorper aliquet aliquet pretium duis\
+ \ litora porttitor.Tristique ex per aptent cras augue mus suspendisse inceptos hac. Amet ultricies\
+ \ sem dui etiam justo. Efficitur ac nisl maecenas eu ac tincidunt. Eget felis hendrerit lacinia\
+ \ commodo eu natoque id himenaeos nibh.
+lblCheckMaintenance.text=Enable Unit Maintenance
+lblCheckMaintenance.tooltip=PLACEHOLDER
+lblMaintenanceDays.text=Base Maintenance Cycle
+lblMaintenanceDays.tooltip=PLACEHOLDER
+lblMaintenanceBonus.text=Maintenance Modifier
+lblMaintenanceBonus.tooltip=PLACEHOLDER
+lblDefaultMaintenanceTime.text=Default Maintenance Time
+lblDefaultMaintenanceTime.tooltip=PLACEHOLDER
+lblUseQualityMaintenance.text=Use Quality Modifiers
+lblUseQualityMaintenance.tooltip=PLACEHOLDER
+lblReverseQualityNames.text=Reverse Quality Names
+lblReverseQualityNames.tooltip=PLACEHOLDER
+lblUseRandomUnitQualities.text=Random New Unit Quality
+lblUseRandomUnitQualities.tooltip=PLACEHOLDER
+lblUsePlanetaryModifiers.text=Use Planetary Modifiers
+lblUsePlanetaryModifiers.tooltip=PLACEHOLDER
+lblUseUnofficialMaintenance.text=Only Damage F-Rated Equipment
+lblUseUnofficialMaintenance.tooltip=PLACEHOLDER
+lblLogMaintenance.text=Write Maintenance Results to MekHQ.log
+lblLogMaintenance.tooltip=PLACEHOLDER
+
+## SuppliesAndAcquisitionTab
+suppliesAndAcquisitionContentTabs.title=Supplies and Acquisition
+
+acquisitionTab.title=Acquisitions
+acquisitionTab.border="It's not about what you need - it's about what you can get. In acquisitions,\
+ \ creativity beats C-Bills."\
+
- Quartermaster Jonas "Scrounger" Voss, Red Talon Mercenaries
+
+deliveryTab.title=Deliveries
+deliveryTab.border="Every part I deliver is a promise that a mek will rise again. Speed is my weapon,\
+ \ and time is the enemy."\
+
- Captain Horace "Hot Wheels" Drake, Midnight Express
+
+planetaryAcquisitionTab.title=Planetary Acquisitions
+planetaryAcquisitionTab.border="On a guerrilla contract, parts are as valuable as ammo. Get what you\
+ \ can, while you can, because tomorrow, it might be gone."\
+
- Lieutenant Jaxon "Jackpot" Hale, Horizon Raiders
+
+techLimitsTab.title=Tech Limits
+techLimitsTab.border="In a universe where we fight with the ghosts of a golden age, technology is a\
+ \ reminder: we are bound by history, but not defined by it."\
+
- Engineer Talia "Patch" Kessler, Stormhounds
+
+# createAcquisitionTab
+lblAcquisitionTab.text=Acquisition Options
+lblAcquisitionTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Tristique non elit\
+ \ potenti suscipit lobortis sollicitudin. Iaculis dis ultrices cursus litora iaculis. Commodo blandit\
+ \ penatibus vitae leo quisque lectus dictum. Duis conubia nisi aliquet phasellus risus nullam massa\
+ \ at. Elementum natoque torquent phasellus suspendisse per aliquet scelerisque. Justo integer\
+ \ faucibus penatibus sem class.
+lblChoiceAcquireSkill.text=Acquisitions Skill
+lblChoiceAcquireSkill.tooltip=PLACEHOLDER
+lblSupportStaffOnly.text=Only Support Personnel Make Acquisition Rolls
+lblSupportStaffOnly.tooltip=PLACEHOLDER
+lblAcquireClanPenalty.text=Penalty for Clan Equipment
+lblAcquireClanPenalty.tooltip=PLACEHOLDER
+lblAcquireISPenalty.text=Penalty for Inner Sphere Equipment
+lblAcquireISPenalty.tooltip=PLACEHOLDER
+lblAcquireWaitingPeriod.text=Acquisition Roll Period Frequency (in days)
+lblAcquireWaitingPeriod.tooltip=PLACEHOLDER
+lblMaxAcquisitions.text=Max Acquisition Rolls per Period
+lblMaxAcquisitions.tooltip=PLACEHOLDER
+
+# createDeliveryTab
+lblDeliveryTab.text=Delivery Options
+lblDeliveryTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod varius congue\
+ \ rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam maximus. Morbi\
+ \ gravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat turpis semper\
+ \ morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida primis\
+ \ vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin porttitor\
+ \ dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam.
+lblNDiceTransitTime.text=Delivery Time
+lblNDiceTransitTime.tooltip=PLACEHOLDER
+lblConstantTransitTime.text=d6+
+lblConstantTransitTime.tooltip=PLACEHOLDER
+lblAcquireMosBonus.text=Delivery Time Reduction (per Margin of Success)
+lblAcquireMosBonus.tooltip=PLACEHOLDER
+lblAcquireMinimum.text=Minimum Delivery Time
+lblAcquireMinimum.tooltip=PLACEHOLDER
+transitUnitNamesDays.text=Days
+transitUnitNamesWeeks.text=Weeks
+transitUnitNamesMonths.text=Months
+
+# createPlanetaryAcquisitionTab
+lblPlanetaryAcquisitionTab.text=Planetary Acquisition Options
+lblPlanetaryAcquisitionTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam.
+
+# createOptionsPanel
+lblUsePlanetaryAcquisitions.text=Use Planetary Acquisitions
+lblUsePlanetaryAcquisitions.tooltip=PLACEHOLDER
+lblMaxJumpPlanetaryAcquisitions.text=Maximum Jump Distance
+lblMaxJumpPlanetaryAcquisitions.tooltip=PLACEHOLDER
+lblPlanetaryAcquisitionsFactionLimits.text=Faction Supply Limits
+lblPlanetaryAcquisitionsFactionLimits.tooltip=PLACEHOLDER
+lblDisallowPlanetaryAcquisitionClanCrossover.text=No Clan-Inner Sphere Supply Sharing
+lblDisallowPlanetaryAcquisitionClanCrossover.tooltip=PLACEHOLDER
+lblDisallowClanPartsFromIS.text=Disallow Clan Parts from Non-Clan Factions
+lblDisallowClanPartsFromIS.tooltip=PLACEHOLDER
+lblPenaltyClanPartsFromIS.text=Non-Clan Acquisition Penalty
+lblPenaltyClanPartsFromIS.tooltip=PLACEHOLDER
+lblUsePlanetaryAcquisitionsVerbose.text=Enable Verbose Reporting
+lblUsePlanetaryAcquisitionsVerbose.tooltip=PLACEHOLDER
+
+# createModifiersPanel
+lblModifiersPanel.text=Modifiers
+lblTechLabel.text=Tech
+lblTechLabel.tooltip=PLACEHOLDER
+lblIndustryLabel.text=Industry
+lblIndustryLabel.tooltip=PLACEHOLDER
+lblOutputLabel.text=Output
+lblOutputLabel.tooltip=PLACEHOLDER
+
+# createTechLimitsTab
+lblTechLimitsTab.text=Tech Limit Options
+lblTechLimitsTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblLimitByYearBox.text=Limit Tech Purchases by Game Year
+lblLimitByYearBox.tooltip=PLACEHOLDER
+lblDisallowExtinctStuffBox.text=Disallow Purchasing of Extinct Tech
+lblDisallowExtinctStuffBox.tooltip=PLACEHOLDER
+lblAllowClanPurchasesBox.text=Allow Purchase of Clan Tech
+lblAllowClanPurchasesBox.tooltip=PLACEHOLDER
+lblAllowISPurchasesBox.text=Allow Purchase of Inner Sphere Tech
+lblAllowISPurchasesBox.tooltip=PLACEHOLDER
+lblAllowCanonOnlyBox.text=Canon Tech Purchases Only
+lblAllowCanonOnlyBox.tooltip=PLACEHOLDER
+lblAllowCanonRefitOnlyBox.text=Canon Refits Only
+lblAllowCanonRefitOnlyBox.tooltip=PLACEHOLDER
+lblChoiceTechLevel.text=Maximum Tech Level
+lblChoiceTechLevel.tooltip=PLACEHOLDER
+lblVariableTechLevelBox.text=Vary Introduction Date by Tech Level
+lblVariableTechLevelBox.tooltip=PLACEHOLDER
+lblUseAmmoByTypeBox.text=Use Ammo Cross-Weapon Compatibility
+lblUseAmmoByTypeBox.tooltip=PLACEHOLDER
+
+## Human Resources Tab
+personnelContentTabs.title=Personnel
+
+# Personnel Tab
+personnelGeneralTab.title=General
+personnelGeneralTab.border="You can replace a 'mek. You can't replace a veteran pilot. Personnel are your most\
+ \ valuable asset, even when they come with attitude."\
+
- Major Helena "Steelheart" Graves, Valiant Shields
+
+personnelLogsTab.title=Personnel Logs
+personnelLogsTab.border="You think piloting a 'mek is stressful? Try keeping a personnel log for a\
+ \ lance full of trigger-happy maniacs."\
+
- Sergeant Dana "Firestorm" Watts, Broken Sword Regiment
+
+personnelInformationTab.title=Personnel Information
+personnelInformationTab.border="Every log entry isn't just data - it's the history of our survival,\
+ \ our victories, and our failures. Keep them well, because one day they'll save us again."\
+
- Sergeant Vic "Crash" Helman, Ironclad Hawks
+
+administratorsTab.title=Administrators
+administratorsTab.border="Administrators don't need medals. They just need enough coffee to survive\
+ \ the paperwork."\
+
- Sergeant Bobby "Scrapheap" Martinez, Steel Raptor Battalion
+
+awardsTab.title=Awards
+awardsTab.border="An award is just metal and ribbon, but the courage it represents is what keeps us\
+ \ fighting when everything else says we should fall."\
+
- Lieutenant Marcus "Viper" Hayes, Storm Bear Company
+
+prisonersAndDependentsTab.title=Prisoners & Dependents
+prisonersAndDependentsTab.border="The strength of a MekWarrior isn't just in the battlefield - it's\
+ \ in how we protect those who can't fight for themselves. Dependents are the reason we fight, not the burden."\
+
- Major Trina "Stormrider" Valdez, Crimson Flame Division
+
+medicalTab.title=Medical
+medicalTab.border="You know it's a bad day when the medbay looks like the hangar bay - bodies and 'meks,\
+ \ both in for repairs."\
+
- Sergeant Alex "Stitches" Boyd, Ironclad Lancers
+
+salariesTab.title=Salaries
+salariesTab.border="A pilot's salary pays for more than just a 'mek - it pays for loyalty, and that's\
+ \ the one thing you can't afford to lose."\
+
-Captain Valen "Hardline" Pierce, Black Talon Mercs
+
+# createGeneralTab
+lblPersonnelGeneralTab.text=General Options
+lblPersonnelGeneralTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseTactics.text=Use Commander Initiative Bonus
+lblUseTactics.tooltip=PLACEHOLDER
+lblUseInitiativeBonus.text=Use Individual Initiative Bonus
+lblUseInitiativeBonus.tooltip=PLACEHOLDER
+lblUseToughness.text=Use Toughness
+lblUseToughness.tooltip=PLACEHOLDER
+lblUseRandomToughness.text=Randomize Toughness
+lblUseRandomToughness.tooltip=PLACEHOLDER
+lblUseArtillery.text=Use Artillery Skill
+lblUseArtillery.tooltip=PLACEHOLDER
+lblUseAbilities.text=Use Special Pilot Abilities (SPAs)
+lblUseAbilities.tooltip=PLACEHOLDER
+lblUseEdge.text=Use Edge
+lblUseEdge.tooltip=PLACEHOLDER
+lblUseSupportEdge.text=Support Personnel Use Edge
+lblUseSupportEdge.tooltip=PLACEHOLDER
+lblUseImplants.text=Use Implants
+lblUseImplants.tooltip=PLACEHOLDER
+lblUseAlternativeQualityAveraging.text=Use Higher-Precision Skill Averaging
+lblUseAlternativeQualityAveraging.tooltip=PLACEHOLDER
+
+# createPersonnelCleanUpPanel
+lblPersonnelCleanUpPanel.text=Personnel Cleanup
+lblUsePersonnelRemoval.text=Enable Personnel Cleanup
+lblUsePersonnelRemoval.tooltip=PLACEHOLDER
+lblUseRemovalExemptCemetery.text=Exempt Dead Personnel
+lblUseRemovalExemptCemetery.tooltip=PLACEHOLDER
+lblUseRemovalExemptRetirees.text=Exempt Retirees
+lblUseRemovalExemptRetirees.tooltip=PLACEHOLDER
+
+# createPersonnelLogsTab
+lblPersonnelLogsTab.text=Personnel Log Options
+lblPersonnelLogsTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseTransfers.text=Use Reassign for Logging
+lblUseTransfers.tooltip=PLACEHOLDER
+lblUseExtendedTOEForceName.text=Use Extended TO&E Names in Log
+lblUseExtendedTOEForceName.tooltip=PLACEHOLDER
+lblPersonnelLogSkillGain.text=Log Skill Gains
+lblPersonnelLogSkillGain.tooltip=PLACEHOLDER
+lblPersonnelLogAbilityGain.text=Log SPA Gains
+lblPersonnelLogAbilityGain.tooltip=PLACEHOLDER
+lblPersonnelLogEdgeGain.text=Log Edge Gains
+lblPersonnelLogEdgeGain.tooltip=PLACEHOLDER
+lblDisplayPersonnelLog.text=Expand Personal Log by Default
+lblDisplayPersonnelLog.tooltip=PLACEHOLDER
+lblDisplayScenarioLog.text=Expand Scenario Log by Default
+lblDisplayScenarioLog.tooltip=PLACEHOLDER
+lblDisplayKillRecord.text=Expand Kill Log by Default
+lblDisplayKillRecord.tooltip=PLACEHOLDER
+
+# createPersonnelInformationTab
+lblPersonnelInformation.text=Personnel Information Options
+lblPersonnelInformationBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseTimeInService.text=Track Time in Service
+lblUseTimeInService.tooltip=PLACEHOLDER
+lblTimeInServiceDisplayFormat.text=Display Time in Service
+lblTimeInServiceDisplayFormat.tooltip=PLACEHOLDER
+lblUseTimeInRank.text=Track Time in Rank
+lblUseTimeInRank.tooltip=PLACEHOLDER
+lblTimeInRankDisplayFormat.text=Display Time in Rank
+lblTimeInRankDisplayFormat.tooltip=PLACEHOLDER
+lblTrackTotalEarnings.text=Track Total Earnings
+lblTrackTotalEarnings.tooltip=PLACEHOLDER
+lblTrackTotalXPEarnings.text=Display Total Earnings
+lblTrackTotalXPEarnings.tooltip=PLACEHOLDER
+lblShowOriginFaction.text=Display Origin Faction
+lblShowOriginFaction.tooltip=PLACEHOLDER
+
+# createAdministratorsTab
+lblAdministratorsTab.text=Administrator Options
+lblAdministratorsTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblAdminsHaveNegotiation.text=Admins Have Negotiation
+lblAdminsHaveNegotiation.tooltip=PLACEHOLDER
+lblAdminExperienceLevelIncludeNegotiation.text=Negotiation Factored into Experience Level
+lblAdminExperienceLevelIncludeNegotiation.tooltip=PLACEHOLDER
+lblAdminsHaveScrounge.text=Admins Have Scrounge
+lblAdminsHaveScrounge.tooltip=PLACEHOLDER
+lblAdminExperienceLevelIncludeScrounge.text=Scrounge Factored into Experience Level
+lblAdminExperienceLevelIncludeScrounge.tooltip=PLACEHOLDER
+
+# createAwardsTab
+lblAwardsTab.text=Awards Options
+lblAwardsTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblAwardBonusStyle.text=Bonuses
+lblAwardBonusStyle.tooltip=PLACEHOLDER
+lblAwardTierSize.text=Tier Size
+lblAwardTierSize.tooltip=PLACEHOLDER
+lblEnableAutoAwards.text=Enable autoAwards
+lblEnableAutoAwards.tooltip=PLACEHOLDER
+lblIssuePosthumousAwards.text=Issue Posthumous Awards
+lblIssuePosthumousAwards.tooltip=PLACEHOLDER
+lblIssueBestAwardOnly.text=Issue Best Award Only
+lblIssueBestAwardOnly.tooltip=PLACEHOLDER
+lblIgnoreStandardSet.text=Ignore the Standard Set
+lblIgnoreStandardSet.tooltip=PLACEHOLDER
+lblAwardSetFilterList.text=Award Set Filter
+lblAwardSetFilterList.tooltip=PLACEHOLDER
+
+# createAutoAwardsFilterPanel
+lblAutoAwardsFilterPanel.text=Award Tracking
+lblEnableContractAwards.text=Contract
+lblEnableContractAwards.tooltip=PLACEHOLDER
+lblEnableFactionHunterAwards.text=Faction Hunter
+lblEnableFactionHunterAwards.tooltip=PLACEHOLDER
+lblEnableInjuryAwards.text=Injury
+lblEnableInjuryAwards.tooltip=PLACEHOLDER
+lblEnableIndividualKillAwards.text=Kill (Individual)
+lblEnableIndividualKillAwards.tooltip=PLACEHOLDER
+lblEnableFormationKillAwards.text=Kill (Formation)
+lblEnableFormationKillAwards.tooltip=PLACEHOLDER
+lblEnableRankAwards.text=Rank
+lblEnableRankAwards.tooltip=PLACEHOLDER
+lblEnableScenarioAwards.text=Scenario
+lblEnableScenarioAwards.tooltip=PLACEHOLDER
+lblEnableSkillAwards.text=Skill
+lblEnableSkillAwards.tooltip=PLACEHOLDER
+lblEnableTheatreOfWarAwards.text=Theatre of War
+lblEnableTheatreOfWarAwards.tooltip=PLACEHOLDER
+lblEnableTimeAwards.text=Time
+lblEnableTimeAwards.tooltip=PLACEHOLDER
+lblEnableTrainingAwards.text=Training
+lblEnableTrainingAwards.tooltip=PLACEHOLDER
+lblEnableMiscAwards.text=Misc
+lblEnableMiscAwards.tooltip=PLACEHOLDER
+
+# createPrisonersAndDependentsTab
+lblPrisonersAndDependentsTab.text=Dependent & Prisoner Options
+lblPrisonersAndDependentsTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+
+# createPrisonersPanel
+lblPrisonersPanel.text=Prisoners
+lblPrisonerCaptureStyle.text=Capture Style
+lblPrisonerCaptureStyle.tooltip=PLACEHOLDER
+lblPrisonerStatus.text=Default Status
+lblPrisonerStatus.tooltip=PLACEHOLDER
+lblPrisonerBabyStatus.text=Prisoner Babies Share Mother's Status
+lblPrisonerBabyStatus.tooltip=PLACEHOLDER
+lblAtBPrisonerDefection.text=Enable Defection
+lblAtBPrisonerDefection.tooltip=PLACEHOLDER
+lblAtBPrisonerRansom.text=Enable Prisoner Ransoms
+lblAtBPrisonerRansom.tooltip=PLACEHOLDER
+
+# createDependentsPanel
+lblDependentsPanel.text=Dependents
+lblUseRandomDependentAddition.text=Random Addition
+lblUseRandomDependentAddition.tooltip=PLACEHOLDER
+lblUseRandomDependentRemoval.text=Random Removal
+lblUseRandomDependentRemoval.tooltip=PLACEHOLDER
+
+# createMedicalTab
+lblMedicalTab.text=Medical Options
+lblMedicalTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseAdvancedMedical.text=Use Advanced Medical
+lblUseAdvancedMedical.tooltip=PLACEHOLDER
+lblHealWaitingPeriod.text=Days Between Healing Checks
+lblHealWaitingPeriod.tooltip=PLACEHOLDER
+lblNaturalHealWaitingPeriod.text=Days Between Natural Healing Checks
+lblNaturalHealWaitingPeriod.tooltip=PLACEHOLDER
+lblMinimumHitsForVehicles.text=Minimum Number of Hits for Vehicle Crew
+lblMinimumHitsForVehicles.tooltip=PLACEHOLDER
+lblUseRandomHitsForVehicles.text=Randomized Vehicle Crew Hits
+lblUseRandomHitsForVehicles.tooltip=PLACEHOLDER
+lblUseTougherHealing.text=Use Tougher Healing
+lblUseTougherHealing.tooltip=PLACEHOLDER
+lblMaximumPatients.text=Beds per Doctor
+lblMaximumPatients.tooltip=PLACEHOLDER
+
+# createSalariesTab
+lblSalariesTab.text=Salary Options
+lblSalariesTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblDisableSecondaryRoleSalary.text=Disable Secondary Role Salaries
+lblDisableSecondaryRoleSalary.tooltip=PLACEHOLDER
+
+# createSalaryMultipliersPanel
+lblSalaryMultipliersPanel.text=Role Multipliers
+lblAntiMekSalary.text=Anti-Mek
+lblAntiMekSalary.tooltip=PLACEHOLDER
+lblSpecialistInfantrySalary.text=Specialist Infantry
+lblSpecialistInfantrySalary.tooltip=PLACEHOLDER
+
+# createExperienceMultipliersPanel
+lblExperienceMultipliersPanel.text=Experience Multipliers
+lblSkillLevelNone.text=None
+lblSkillLevelNone.tooltip=PLACEHOLDER
+lblSkillLevelUltra-Green.text=Ultra-Green
+lblSkillLevelUltra-Green.tooltip=PLACEHOLDER
+lblSkillLevelGreen.text=Green
+lblSkillLevelGreen.tooltip=PLACEHOLDER
+lblSkillLevelRegular.text=Regular
+lblSkillLevelRegular.tooltip=PLACEHOLDER
+lblSkillLevelVeteran.text=Veteran
+lblSkillLevelVeteran.tooltip=PLACEHOLDER
+lblSkillLevelElite.text=Elite
+lblSkillLevelElite.tooltip=PLACEHOLDER
+lblSkillLevelHeroic.text=Heroic
+lblSkillLevelHeroic.tooltip=PLACEHOLDER
+lblSkillLevelLegendary.text=Legendary
+lblSkillLevelLegendary.tooltip=PLACEHOLDER
+
+# createBaseSalariesPanel
+lblBaseSalariesPanel.text=Base Salaries
+
+# Biography Tab
+biographyContentTabs.title=Biography
+
+biographyGeneralTab.title=General
+biographyGeneralTab.border="Every MekWarrior starts somewhere different, but we all end up the same:\
+ \ in the cockpit, staring down the impossible, and finding a way through."\
+
- Lieutenant Adam "Burnout" Keller, Blackthorn Marauders
+
+backgroundsTab.title=Backgrounds
+backgroundsTab.border="From noble houses to street gangs, once you're in the cockpit, we're all the\
+ \ same. Your past might shape you, but your future is yours to command."\
+
- Lieutenant Marcus "Ghost" Walker, Onyx Fang Company
+
+deathTab.title=Death
+deathTab.border="School didn't teach me how to explode, but I learn fast."\
+
- Sergeant Pete "Wildfire" Watson, Steel Viper Unit
+
+educationTab.title=Education
+educationTab.border="You can teach someone to pilot a 'mek, but you can't teach them how to survive\
+ \ a battlefield. That education comes with time - and scars."\
+
- Lieutenant Hannah "Stinger" Quinn, Ironclad Rangers
+
+nameAndPortraitGenerationTab.title=Name & Portraits
+nameAndPortraitGenerationTab.border="Your name might get you noticed, but it's your actions that make\
+ \ them remember your face. Make every battle count."\
+
- Lieutenant Sara "Nightshade" Grey, Ravenheart Company
+
+rankTab.title=Rank Systems
+rankTab.border="Rank isn't about authority - it's about responsibility. Every step up means you're\
+ \ carrying more than your own survival."\
+
-Captain Maya "Wildcard" Hayes, Black Viper Squadron
+
+# createGeneralTab
+lblBiographyGeneralTab.text=General Options
+lblBiographyGeneralTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseDylansRandomXP.text=Use Random XP
+lblUseDylansRandomXP.tooltip=PLACEHOLDER
+lblGender.text=Percent Female
+lblGender.tooltip=PLACEHOLDER
+lblNonBinaryDiceSize.text=Non-Binary Personnel Chance: 1 in
+lblNonBinaryDiceSize.tooltip=PLACEHOLDER
+lblFamilyDisplayLevel.text=Family Display Depth
+lblFamilyDisplayLevel.tooltip=PLACEHOLDER
+
+# createAnniversariesPanel
+lblAnniversariesPanel.text=Anniversaries
+lblAnnounceBirthdays.text=Announce Birthdays
+lblAnnounceBirthdays.tooltip=PLACEHOLDER
+lblAnnounceRecruitmentAnniversaries.text=Announce Recruitment Anniversaries
+lblAnnounceRecruitmentAnniversaries.tooltip=PLACEHOLDER
+lblAnnounceOfficersOnly.text=Officers Only
+lblAnnounceOfficersOnly.tooltip=PLACEHOLDER
+lblAnnounceChildBirthdays.text=Always Announce 18th Birthdays
+lblAnnounceChildBirthdays.tooltip=PLACEHOLDER
+
+# createBackgroundsTab
+lblBackgroundsTab.text=Background Options
+lblBackgroundsTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseRandomPersonalities.text=Assign Random Personalities
+lblUseRandomPersonalities.tooltip=PLACEHOLDER
+lblUseRandomPersonalityReputation.text=Personality Influences Reputation
+lblUseRandomPersonalityReputation.tooltip=PLACEHOLDER
+lblUseIntelligenceXpMultiplier.text=Intelligence Influences XP Costs
+lblUseIntelligenceXpMultiplier.tooltip=PLACEHOLDER
+lblUseSimulatedRelationships.text=Simulate Background Relationships
+lblUseSimulatedRelationships.tooltip=PLACEHOLDER
+
+# createRandomOriginOptionsPanel
+lblRandomOriginOptionsPanel.text=Origins
+lblRandomizeOrigin.text=Randomize Origin
+lblRandomizeOrigin.tooltip=PLACEHOLDER
+lblRandomizeDependentsOrigin.text=Randomize Dependent Origins
+lblRandomizeDependentsOrigin.tooltip=PLACEHOLDER
+lblRandomizeAroundSpecifiedPlanet.text=Randomize Around Specific Planet
+lblRandomizeAroundSpecifiedPlanet.tooltip=PLACEHOLDER
+lblSpecifiedSystemFactionSpecific.text=Faction Specific
+lblSpecifiedSystemFactionSpecific.tooltip=PLACEHOLDER
+lblSpecifiedSystem.text=System
+lblSpecifiedSystem.tooltip=PLACEHOLDER
+lblSpecifiedPlanet.text=Planet
+lblSpecifiedPlanet.tooltip=PLACEHOLDER
+lblOriginSearchRadius.text=Random Origin Radius
+lblOriginSearchRadius.tooltip=PLACEHOLDER
+lblOriginDistanceScale.text=Distance Scale
+lblOriginDistanceScale.tooltip=PLACEHOLDER
+lblAllowClanOrigins.text=Allow Clan Origins
+lblAllowClanOrigins.tooltip=PLACEHOLDER
+lblExtraRandomOrigin.text=Extra Random Origins
+lblExtraRandomOrigin.tooltip=PLACEHOLDER
+
+# createDeathTab
+lblDeathTab.text=Death Options
+lblDeathTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblKeepMarriedNameUponSpouseDeath.text=Keep Married Name on Spouse Death
+lblKeepMarriedNameUponSpouseDeath.tooltip=PLACEHOLDER
+lblRandomDeathMethod.text=Random Death Method
+lblRandomDeathMethod.tooltip=PLACEHOLDER
+lblUseRandomClanPersonnelDeath.text=Enable Random Clan Death
+lblUseRandomClanPersonnelDeath.tooltip=PLACEHOLDER
+lblUseRandomPrisonerDeath.text=Enable Random Prisoner Death
+lblUseRandomPrisonerDeath.tooltip=PLACEHOLDER
+lblUseRandomDeathSuicideCause.text=Enable Cause of Death: Suicide
+lblUseRandomDeathSuicideCause.tooltip=PLACEHOLDER
+lblPercentageRandomDeathChance.text=Random Death Percentage
+lblPercentageRandomDeathChance.tooltip=PLACEHOLDER
+
+# createDeathAgeGroupsPanel
+lblDeathAgeGroupsPanel.text=Enable Death by Age Group
+
+# createEducationTab
+lblEducationTab.text=Education Options
+lblEducationTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseEducationModule.text=Enable Education
+lblUseEducationModule.tooltip=PLACEHOLDER
+lblCurriculumXpRate.text=Base XP Rate
+lblCurriculumXpRate.tooltip=PLACEHOLDER
+lblMaximumJumpCount.text=Maximum Jump Radius
+lblMaximumJumpCount.tooltip=PLACEHOLDER
+lblUseReeducationCamps.text=Enable Reeducation Camp Faction Changes
+lblUseReeducationCamps.tooltip=PLACEHOLDER
+lblEnableOverrideRequirements.text=Override Requirements
+lblEnableOverrideRequirements.tooltip=PLACEHOLDER
+lblShowIneligibleAcademies.text=Show Ineligible Academies
+lblShowIneligibleAcademies.tooltip=PLACEHOLDER
+lblEntranceExamBaseTargetNumber.text=Entrance Exam Target Number
+lblEntranceExamBaseTargetNumber.tooltip=PLACEHOLDER
+lblEntranceExamBaseTargetNumberPost.text=- Faculty Skill + Intelligence Modifier
+lblEntranceExamBaseTargetNumberPost.tooltip=PLACEHOLDER
+
+# createEnableStandardSetsPanel
+lblEnableStandardSetsPanel.text=Standard Sets
+lblEnableLocalAcademies.text=Local Academies
+lblEnableLocalAcademies.tooltip=PLACEHOLDER
+lblEnablePrestigiousAcademies.text=Prestigious Academies
+lblEnablePrestigiousAcademies.tooltip=PLACEHOLDER
+lblEnableUnitEducation.text=Unit Education
+lblEnableUnitEducation.tooltip=PLACEHOLDER
+
+# createXpAndSkillBonusesPanel
+lblXpAndSkillBonusesPanel.text=Faculty XP & Skill Bonuses
+lblEnableBonuses.text=Enable Graduation Bonuses
+lblEnableBonuses.tooltip=PLACEHOLDER
+lblFacultyXpMultiplier.text=Faculty XP Multiplier
+lblFacultyXpMultiplier.tooltip=PLACEHOLDER
+
+# createDropoutChancePanel
+lblDropoutChancePanel.text=Weekly Dropout Chances
+lblAdultDropoutChance.text=Adult Dropout Chance: 1 in
+lblAdultDropoutChance.tooltip=PLACEHOLDER
+lblChildrenDropoutChance.text=Child Dropout Chance: 1 in
+lblChildrenDropoutChance.tooltip=PLACEHOLDER
+
+# createAccidentsAndEventsPanel
+lblAccidentsAndEventsPanel.text=Weekly Accidents & Events
+lblAllAges.text=All Ages Affected
+lblAllAges.tooltip=PLACEHOLDER
+lblMilitaryAcademyAccidents.text=Military Accidents Chance: 1 in
+lblMilitaryAcademyAccidents.tooltip=PLACEHOLDER
+
+# createNameAndPortraitGenerationTab
+lblNameAndPortraitGenerationTab.text=Name and Portrait Generation Options
+lblNameAndPortraitGenerationTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseOriginFactionForNames.text=Assign Names Based on Origin Faction
+lblUseOriginFactionForNames.tooltip=PLACEHOLDER
+lblFactionNames.text=Faction
+lblFactionNames.tooltip=PLACEHOLDER
+lblAssignPortraitOnRoleChange.text=Reassign Portrait on Role Change
+lblAssignPortraitOnRoleChange.tooltip=PLACEHOLDER
+
+# createRandomPortraitPanel
+lblRandomPortraitPanel.text=Portrait Assignment
+lblAllPortraitsBox.text=All Roles
+lblNoPortraitsBox.text=No Roles
+
+# createRankTab
+lblRankTab.text=Rank Systems
+lblRankTabBody.text=You can use the table here to assign ranks for your campaign. You can use one of\
+ \ the preset rank systems from the pull-down menu, or you can design your own by creating a custom\
+ \ rank system.\
+
You can save a single rank system as part of the campaign, with any additional custom rank systems\
+ \ to be saved in the user data file instead. Any additional campaign rank systems will be deleted.\
+
You can also assign custom multipliers for salary. These multipliers don't need to take into\
+ \ account the officer multiplier which is addressed elsewhere.\
+
\
+
WARNING:\
+
1) This dialog doesn't warn about the deletion of any campaign custom rank systems that aren't\
+ \ the selected rank system for the campaign at this time.\
+
2) All personnel ranks will be revalidated when this is changed, to migrate them to the proper\
+ \ setup for their new rank system.\
+
3) This dialog does not validate the data at this time, so be careful with circular logic and\
+ \ ensure you have a valid E0 rank (one MUST be a name like "None" or "Grunt", with "None" specifically\
+ \ handled in code to show as a blank string when the rank name is displayed).
+
+# Turnover and Rention Tab
+turnoverAndRetentionContentTabs.title=Turnover & Retention
+
+turnoverTab.title=Turnover
+turnoverTab.border="For a MekWarrior, retirement is a strange thing. We spend our lives in battle,\
+ \ and when the guns go silent, we find out who we are without them."\
+
- Colonel Sofia "Whisper" Talon, Ironclad Irregulars
+
+fatigueTab.title=Fatigue
+fatigueTab.border="Fatigue doesn't just slow you down; it makes you sloppy. And sloppy gets you killed."\
+
- Lieutenant Kayla "Quickdraw" Frost, Shadow Talon Mercs
+
+# createTurnoverTab
+lblTurnoverTab.text=Turnover Options
+lblTurnoverTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseRandomRetirement.text=Enable Random Turnover
+lblUseRandomRetirement.tooltip=PLACEHOLDER
+
+# createSettingsPanel
+lblSettingsPanel.text=Settings
+lblTurnoverFixedTargetNumber.text=Target Number
+lblTurnoverFixedTargetNumber.tooltip=PLACEHOLDER
+lblTurnoverFrequency.text=Frequency
+lblTurnoverFrequency.tooltip=PLACEHOLDER
+lblUseContractCompletionRandomRetirement.text=Enable End of Contract Turnover
+lblUseContractCompletionRandomRetirement.tooltip=PLACEHOLDER
+lblUseRandomFounderTurnover.text=Enable Founder Turnover
+lblUseRandomFounderTurnover.tooltip=PLACEHOLDER
+lblTrackOriginalUnit.text=Track Original Unit
+lblTrackOriginalUnit.tooltip=PLACEHOLDER
+lblAeroRecruitsHaveUnits.text=AeroTek Recruits Have Units
+lblAeroRecruitsHaveUnits.tooltip=PLACEHOLDER
+lblUseSubContractSoldiers.text=Sub-Contract Soldiers
+lblUseSubContractSoldiers.tooltip=PLACEHOLDER
+lblServiceContractDuration.text=Service Contract Duration
+lblServiceContractDuration.tooltip=PLACEHOLDER
+lblServiceContractModifier.text=Service Contract Modifier
+lblServiceContractModifier.tooltip=PLACEHOLDER
+lblPayBonusDefault.text=Automate Retention Bonuses
+lblPayBonusDefault.tooltip=PLACEHOLDER
+lblPayBonusDefaultThreshold.text=Bonus Threshold
+lblPayBonusDefaultThreshold.tooltip=PLACEHOLDER
+
+# createModifiersPanel
+lblTurnoverModifiersPanel.text=Modifiers
+lblUseCustomRetirementModifiers.text=Custom
+lblUseCustomRetirementModifiers.tooltip=PLACEHOLDER
+lblUseFatigueModifiers.text=Fatigue Modifiers
+lblUseFatigueModifiers.tooltip=PLACEHOLDER
+lblUseSkillModifiers.text=Desirability
+lblUseSkillModifiers.tooltip=PLACEHOLDER
+lblUseAgeModifiers.text=Age
+lblUseAgeModifiers.tooltip=PLACEHOLDER
+lblUseUnitRatingModifiers.text=Unit Reputation
+lblUseUnitRatingModifiers.tooltip=PLACEHOLDER
+lblUseFactionModifiers.text=Faction
+lblUseFactionModifiers.tooltip=PLACEHOLDER
+lblUseMissionStatusModifiers.text=Mission Status
+lblUseMissionStatusModifiers.tooltip=PLACEHOLDER
+lblUseHostileTerritoryModifiers.text=Hostile Territory
+lblUseHostileTerritoryModifiers.tooltip=PLACEHOLDER
+lblUseFamilyModifiers.text=Family
+lblUseFamilyModifiers.tooltip=PLACEHOLDER
+lblUseLoyaltyModifiers.text=Loyalty
+lblUseLoyaltyModifiers.tooltip=PLACEHOLDER
+lblUseHideLoyalty.text=Hide Loyalty
+lblUseHideLoyalty.tooltip=PLACEHOLDER
+
+# createPayoutsPanel
+lblPayoutsPanel.text=Payouts
+lblPayoutRateOfficer.text=Officer Rate
+lblPayoutRateOfficer.tooltip=PLACEHOLDER
+lblPayoutRateEnlisted.text=Enlisted Rate
+lblPayoutRateEnlisted.tooltip=PLACEHOLDER
+lblPayoutRetirementMultiplier.text=Retirement Multiplier
+lblPayoutRetirementMultiplier.tooltip=PLACEHOLDER
+lblUsePayoutServiceBonus.text=Enable Service Bonuses
+lblUsePayoutServiceBonus.tooltip=PLACEHOLDER
+lblPayoutServiceBonusRate.text=Bonus %
+lblPayoutServiceBonusRate.tooltip=PLACEHOLDER
+
+# createUnitCohesionPanel
+lblUnitCohesionPanel.text=Unit Cohesion
+lblUseAdministrativeStrain.text=Enable Administrative Strain
+lblUseAdministrativeStrain.tooltip=PLACEHOLDER
+lblUseManagementSkill.text=Enable Management Skill
+lblUseManagementSkill.tooltip=PLACEHOLDER
+
+# createAdministrativeStrainPanel
+lblAdministrativeStrain.text=Administrative Strain
+lblAdministrativeCapacity.text=Administrative Capacity
+lblAdministrativeCapacity.tooltip=PLACEHOLDER
+lblMultiCrewStrainDivider.text=Multi-Crew Strain Divider
+lblMultiCrewStrainDivider.tooltip=PLACEHOLDER
+
+# createManagementSkill
+lblManagementSkill.text=Management Skill
+lblUseCommanderLeadershipOnly.text=Use Commander's Leadership Only
+lblUseCommanderLeadershipOnly.tooltip=PLACEHOLDER
+lblManagementSkillPenalty.text=Unskilled Penalty
+lblManagementSkillPenalty.tooltip=PLACEHOLDER
+
+# createFatigueTab
+lblFatigueTab.text=Fatigue Options
+lblFatigueTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseFatigue.text=Enable Fatigue
+lblUseFatigue.tooltip=PLACEHOLDER
+lblFatigueRate.text=Fatigue Rate
+lblFatigueRate.tooltip=PLACEHOLDER
+lblUseInjuryFatigue.text=Injuries Increase Fatigue
+lblUseInjuryFatigue.tooltip=PLACEHOLDER
+lblFieldKitchenCapacity.text=Field Kitchen Capacity
+lblFieldKitchenCapacity.tooltip=PLACEHOLDER
+lblFieldKitchenIgnoreNonCombatants.text=Ignore Non-Combatants
+lblFieldKitchenIgnoreNonCombatants.tooltip=PLACEHOLDER
+lblFatigueLeaveThreshold.text=Automatic Leave Threshold
+lblFatigueLeaveThreshold.tooltip=PLACEHOLDER
+
+## Relationships Tab
+relationshipsContentTabs.title=Relationships
+
+marriageTab.title=Marriage
+marriageTab.border="In a universe filled with war and chaos, marriage is the one alliance\
+ \ that keeps you grounded. When the battles end, it's the bond you fight to protect."\
+
- Lieutenant Elara "Sunburst" Tate, Steelclaw Company
+
+divorceTab.title=Divorce
+divorceTab.border="Divorce is just like ejecting from a 'mek: it's messy, expensive, and\
+ \ you're lucky if you escape in one piece."\
+
- Sergeant Quinn "Deadeye" Mallory, Crimson Fang Mercs
+
+procreationTab.title=Procreation
+procreationTab.border="In this galaxy, raising kids is tougher than raising a lance. At\
+ \ least 'meks come with an instruction manual."\
+
- Captain Dani "Ironheart" Cole, Steel Talon Company
+
+# createMarriageTab
+lblMarriageTab.text=Marriage Options
+lblMarriageTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseManualMarriages.text=Enable Manual Marriages
+lblUseManualMarriages.tooltip=PLACEHOLDER
+lblUseClanPersonnelMarriages.text=Enable Clan Marriages
+lblUseClanPersonnelMarriages.tooltip=PLACEHOLDER
+lblUsePrisonerMarriages.text=Enable Prisoner Marriages
+lblUsePrisonerMarriages.tooltip=PLACEHOLDER
+lblNoInterestInMarriageDiceSize.text=No Interest in Marriage Chance: 1 in
+lblNoInterestInMarriageDiceSize.tooltip=PLACEHOLDER
+lblCheckMutualAncestorsDepth.text=Minimum Ancestor Depth
+lblCheckMutualAncestorsDepth.tooltip=PLACEHOLDER
+lblLogMarriageNameChanges.text=Log Name Changes
+lblLogMarriageNameChanges.tooltip=PLACEHOLDER
+
+# createRandomMarriagePanel
+lblRandomMarriages.text=Random Marriages
+lblRandomMarriageMethod.text=Random Marriage Method
+lblRandomMarriageMethod.tooltip=PLACEHOLDER
+lblUseRandomClanPersonnelMarriages.text=Enable Random Clan Marriages
+lblUseRandomClanPersonnelMarriages.tooltip=PLACEHOLDER
+lblUseRandomPrisonerMarriages.text=Enable Random Prisoner Marriages
+lblUseRandomPrisonerMarriages.tooltip=PLACEHOLDER
+lblRandomMarriageAgeRange.text=Random Marriage Age Band
+lblRandomMarriageAgeRange.tooltip=PLACEHOLDER
+
+# createPercentageRandomMarriagePanel
+lblPercentageRandomMarriagePanel.text=Marriage Dice
+lblRandomMarriageOppositeSexDiceSize.text=Opposite Sex Marriage Chance: 1 in
+lblRandomMarriageOppositeSexDiceSize.tooltip=PLACEHOLDER
+lblRandomSameSexMarriageDiceSize.text=Same-Sex Marriage Chance: 1 in
+lblRandomSameSexMarriageDiceSize.tooltip=PLACEHOLDER
+lblRandomNewDependentMarriage.text=Inter-Unit Marriage Chance: 1 in
+lblRandomNewDependentMarriage.tooltip=PLACEHOLDER
+
+# createDivorceTab
+lblDivorceTab.text=Divorce Options
+lblDivorceTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseManualDivorce.text=Enable Manual Divorce
+lblUseManualDivorce.tooltip=PLACEHOLDER
+lblUseClanPersonnelDivorce.text=Enable Manual Clan Divorce
+lblUseClanPersonnelDivorce.tooltip=PLACEHOLDER
+lblUsePrisonerDivorce.text=Enable Manual Prisoner Divorce
+lblUsePrisonerDivorce.tooltip=PLACEHOLDER
+
+# createRandomDivorcePanel
+lblRandomDivorcePanel.text=Random Divorce
+lblRandomDivorceMethod.text=Random Divorce Method
+lblRandomDivorceMethod.tooltip=PLACEHOLDER
+lblUseRandomOppositeSexDivorce.text=Use Random Opposite Sex Divorce
+lblUseRandomOppositeSexDivorce.tooltip=PLACEHOLDER
+lblUseRandomSameSexDivorce.text=Use Random Same Sex Divorce
+lblUseRandomSameSexDivorce.tooltip=PLACEHOLDER
+lblUseRandomClanPersonnelDivorce.text=Use Random Clan Divorce
+lblUseRandomClanPersonnelDivorce.tooltip=PLACEHOLDER
+lblUseRandomPrisonerDivorce.text=Use Random Prisoner Divorce
+lblUseRandomPrisonerDivorce.tooltip=PLACEHOLDER
+lblRandomDivorceDiceSize.text=Random Divorce Chance: 1 in
+lblRandomDivorceDiceSize.tooltip=PLACEHOLDER
+
+# createProcreationTab
+lblProcreationTab.text=Procreation Options
+lblProcreationTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+
+# createProcreationGeneralOptionsPanel
+lblUseManualProcreation.text=Enable Manual Procreation
+lblUseManualProcreation.tooltip=PLACEHOLDER
+lblUseClanPersonnelProcreation.text=Enable Clan Procreation
+lblUseClanPersonnelProcreation.tooltip=PLACEHOLDER
+lblUsePrisonerProcreation.text=Enable Prisoner Procreation
+lblUsePrisonerProcreation.tooltip=PLACEHOLDER
+lblMultiplePregnancyOccurrences.text=Multiple Pregnancy Chance: 1 in
+lblMultiplePregnancyOccurrences.tooltip=PLACEHOLDER
+lblBabySurnameStyle.text=Baby Surname Style
+lblBabySurnameStyle.tooltip=PLACEHOLDER
+lblAssignNonPrisonerBabiesFounderTag.text=Non-Prisoner Babies are Founders
+lblAssignNonPrisonerBabiesFounderTag.tooltip=PLACEHOLDER
+lblAssignChildrenOfFoundersFounderTag.text=Children of Founders are Founders
+lblAssignChildrenOfFoundersFounderTag.tooltip=PLACEHOLDER
+lblDetermineFatherAtBirth.text=Determine Father at Birth
+lblDetermineFatherAtBirth.tooltip=PLACEHOLDER
+lblDisplayTrueDueDate.text=Display True Due Date
+lblDisplayTrueDueDate.tooltip=PLACEHOLDER
+lblNoInterestInChildrenDiceSize.text=No Interest in Children Chance: 1 in
+lblNoInterestInChildrenDiceSize.tooltip=PLACEHOLDER
+lblUseMaternityLeave.text=Enable Automatic Maternity Leave
+lblUseMaternityLeave.tooltip=PLACEHOLDER
+lblLogProcreation.text=Log Procreation
+lblLogProcreation.tooltip=PLACEHOLDER
+
+# createRandomProcreationPanel
+lblRandomProcreationPanel.text=Random Procreation
+lblRandomProcreationMethod.text=Random Procreation Method
+lblRandomProcreationMethod.tooltip=PLACEHOLDER
+lblUseRelationshiplessRandomProcreation.text=Enable Random Relationshipless Procreation
+lblUseRelationshiplessRandomProcreation.tooltip=PLACEHOLDER
+lblUseRandomClanPersonnelProcreation.text=Enable Random Clan Procreation
+lblUseRandomClanPersonnelProcreation.tooltip=PLACEHOLDER
+lblUseRandomPrisonerProcreation.text=Enable Random Prisoner Procreation
+lblUseRandomPrisonerProcreation.tooltip=PLACEHOLDER
+lblRandomProcreationRelationshipDiceSize.text=Normal Procreation Chance: 1 in
+lblRandomProcreationRelationshipDiceSize.tooltip=PLACEHOLDER
+lblRandomProcreationRelationshiplessDiceSize.text=Relationshipless Procreation Chance: 1 in
+lblRandomProcreationRelationshiplessDiceSize.tooltip=PLACEHOLDER
+
+# Finances Tab
+financesContentTabs.title=Finances
+
+financesGeneralTab.title=General
+financesGeneralTab.border="War is expensive. If the enemy doesn't kill you, the repair bills might."\
+
- Sergeant Tara "Grease" Hall, Red Star Mercenaries
+
+priceMultipliersTab.title=Price Multipliers
+priceMultipliersTab.border="The used parts market is where dreams are built - and nightmares are patched\
+ \ together. Just make sure the part you're buying doesn't come with someone else's curse."\
+
- Captain Nia "Jackal" Thorne, Shadowblade Lancers
+
+# createFinancesGeneralOptionsTab
+lblFinancesGeneralTab.text=General Options
+lblFinancesGeneralTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+
+# createPaymentsPanel
+lblPaymentsPanel.text=Payments
+lblPayForPartsBox.text=Pay For Parts
+lblPayForPartsBox.tooltip=PLACEHOLDER
+lblPayForRepairsBox.text=Pay For Repairs
+lblPayForRepairsBox.tooltip=PLACEHOLDER
+lblPayForUnitsBox.text=Pay For Units
+lblPayForUnitsBox.tooltip=PLACEHOLDER
+lblPayForSalariesBox.text=Pay For Salaries
+lblPayForSalariesBox.tooltip=PLACEHOLDER
+lblPayForOverheadBox.text=Pay For Overhead
+lblPayForOverheadBox.tooltip=PLACEHOLDER
+lblPayForMaintainBox.text=Pay For Maintenance
+lblPayForMaintainBox.tooltip=PLACEHOLDER
+lblPayForTransportBox.text=Transport
+lblPayForTransportBox.tooltip=PLACEHOLDER
+lblPayForRecruitmentBox.text=Recruitment
+lblPayForRecruitmentBox.tooltip=PLACEHOLDER
+
+# createGeneralOptionsPanel
+lblUseLoanLimitsBox.text=Available Loans Based on Unit Reputation
+lblUseLoanLimitsBox.tooltip=PLACEHOLDER
+lblUsePercentageMaintenanceBox.text=Enable Percentage-Based Maintenance Costs
+lblUsePercentageMaintenanceBox.tooltip=PLACEHOLDER
+lblUseExtendedPartsModifierBox.text=Enabled Extended Spare Parts Modifiers
+lblUseExtendedPartsModifierBox.tooltip=PLACEHOLDER
+lblUsePeacetimeCostBox.text=Enable Peacetime Operating Costs
+lblUsePeacetimeCostBox.tooltip=PLACEHOLDER
+lblShowPeacetimeCostBox.text=Breakdown Operating Costs
+lblShowPeacetimeCostBox.tooltip=PLACEHOLDER
+lblFinancialYearDuration.text=Financial Year Duration
+lblFinancialYearDuration.tooltip=PLACEHOLDER
+lblNewFinancialYearFinancesToCSVExportBox.text=Export Finances as CSV Table on Term End
+lblNewFinancialYearFinancesToCSVExportBox.tooltip=PLACEHOLDER
+
+# createSalesPanel
+lblSalesPanel.text=Sales
+lblSellUnitsBox.text=Enable the Sale of Units
+lblSellUnitsBox.tooltip=PLACEHOLDER
+lblSellPartsBox.text=Enable the Sale of Parts
+lblSellPartsBox.tooltip=PLACEHOLDER
+
+# createTaxesPanel
+lblTaxesPanel.text=Taxes
+lblUseTaxesBox.text=Enable Taxes
+lblUseTaxesBox.tooltip=PLACEHOLDER
+lblTaxesPercentage.text=Tax Percentage
+lblTaxesPercentage.tooltip=PLACEHOLDER
+
+# createSharesPanel
+lblSharesPanel.text=Shares
+lblUseShareSystem.text=Enable Shares
+lblUseShareSystem.tooltip=PLACEHOLDER
+lblSharesForAll.text=All Personnel Have Shares
+lblSharesForAll.tooltip=PLACEHOLDER
+
+# createFinancesGeneralOptionsTab
+lblPriceMultipliersTab.text=Price Multiplier Options
+lblPriceMultipliersTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+
+# createGeneralMultipliersPanel
+lblGeneralMultipliersPanel.text=General
+lblCommonPartPriceMultiplier.text=Common Parts
+lblCommonPartPriceMultiplier.tooltip=PLACEHOLDER
+lblInnerSphereUnitPriceMultiplier.text=Inner Sphere Units
+lblInnerSphereUnitPriceMultiplier.tooltip=PLACEHOLDER
+lblInnerSpherePartPriceMultiplier.text=Inner Sphere Parts
+lblInnerSpherePartPriceMultiplier.tooltip=PLACEHOLDER
+lblClanUnitPriceMultiplier.text=Clan Units
+lblClanUnitPriceMultiplier.tooltip=PLACEHOLDER
+lblClanPartPriceMultiplier.text=Clan Parts
+lblClanPartPriceMultiplier.tooltip=PLACEHOLDER
+lblMixedTechUnitPriceMultiplier.text=Mixed Units
+lblMixedTechUnitPriceMultiplier.tooltip=PLACEHOLDER
+
+# createUsedPartsMultiplierPanel
+lblUsedPartsMultiplierPanel.text=Used Parts
+
+# createOtherMultipliersPanel
+lblOtherMultipliersPanel.text=Other
+lblDamagedPartsValueMultiplier.text=Damaged Parts
+lblDamagedPartsValueMultiplier.tooltip=PLACEHOLDER
+lblUnrepairablePartsValueMultiplier.text=Irreparable Parts
+lblUnrepairablePartsValueMultiplier.tooltip=PLACEHOLDER
+lblCancelledOrderRefundMultiplier.text=Cancelled Order Refund
+lblCancelledOrderRefundMultiplier.tooltip=PLACEHOLDER
+
+# Markets Tab
+marketsContentTabs.title=Markets
+
+personnelMarketTab.title=Personnel
+personnelMarketTab.border="Every hiring hall is filled with possibilities. Behind every handshake is\
+ \ a story waiting to unfold - and sometimes, those stories shape the galaxy."\
+
- Sergeant Max "Rustbucket" Carver, Steel Fangs Mercenaries
+
+unitMarketTab.title=Units
+unitMarketTab.border="Buying a new mech is exciting - right up until you see the repair bill after\
+ \ your first mission. Then it's just another hole in your wallet."\
+
- Sergeant Kyle "Scrapheap" Carter, Black Talon Mercenaries
+
+contractMarketTab.title=Contracts
+contractMarketTab.border="Accepting a contract isn't just about the money - it's about knowing when\
+ \ to walk away and when to take the risk. Every deal comes with strings attached."\
+
- Captain Mika "Frostbite" Kline, Iceheart Marauders
+
+# createPersonnelMarketTab
+lblPersonnelMarketTab.text=Personnel Market Options
+lblPersonnelMarketTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+
+# createPersonnelMarketGeneralOptionsPanel
+lblPersonnelMarketType.text=Market Method
+lblPersonnelMarketType.tooltip=PLACEHOLDER
+lblPersonnelMarketDylansWeight.text=Common Unit Type Weight
+lblPersonnelMarketDylansWeight.tooltip=PLACEHOLDER
+lblPersonnelMarketReportRefresh.text=Post Report on Market Refresh
+lblPersonnelMarketReportRefresh.tooltip=PLACEHOLDER
+lblUsePersonnelHireHiringHallOnly.text=Hiring Halls & Capitals Only
+lblUsePersonnelHireHiringHallOnly.tooltip=PLACEHOLDER
+
+# createPersonnelMarketRemovalOptionsPanel
+lblPersonnelMarketRemovalOptionsPanel.text=Removal Target Numbers
+
+# createUnitMarketTab
+lblUnitMarketTab.text=Unit Market Options
+lblUnitMarketTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUnitMarketMethod.text=Market Method
+lblUnitMarketMethod.tooltip=PLACEHOLDER
+lblUnitMarketRegionalMekVariations.text=Enable Faction 'Mek Weight Variance
+lblUnitMarketRegionalMekVariations.tooltip=PLACEHOLDER
+lblUnitMarketSpecialUnitChance.text=Special Vehicle Chance: 1 in
+lblUnitMarketSpecialUnitChance.tooltip=PLACEHOLDER
+lblUnitMarketRarityModifier.text=Unit Rarity Modifier
+lblUnitMarketRarityModifier.tooltip=PLACEHOLDER
+lblInstantUnitMarketDelivery.text=Enable Instant Deliveries
+lblInstantUnitMarketDelivery.tooltip=PLACEHOLDER
+lblUnitMarketReportRefresh.text=Post Report on Market Refresh
+lblUnitMarketReportRefresh.tooltip=PLACEHOLDER
+
+# createContractMarketTab
+lblContractMarketTab.text=Contract Market Options
+lblContractMarketTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+
+# createContractMarketGeneralOptionsPanel
+lblContractMarketMethod.text=Market Method
+lblContractMarketMethod.tooltip=PLACEHOLDER
+lblContractSearchRadius.text=Search Radius
+lblContractSearchRadius.tooltip=PLACEHOLDER
+lblVariableContractLength.text=Vary Contract Lengths
+lblVariableContractLength.tooltip=PLACEHOLDER
+lblContractMarketReportRefresh.text=Post Report on Market Refresh
+lblContractMarketReportRefresh.tooltip=PLACEHOLDER
+lblCoontractMaxSalvagePercentage.text=Max Salvage Percent
+lblCoontractMaxSalvagePercentage.tooltip=PLACEHOLDER
+lblDropShipBonusPercentage.text=DropShip Bonus Percent
+lblDropShipBonusPercentage.tooltip=PLACEHOLDER
+
+# createMercenaryPanel
+lblContractPayPanel.text=Contract Pay
+lblContractEquipment.text=TO&E Value Influences Pay
+lblContractEquipment.tooltip=PLACEHOLDER
+lblEquipContractSaleValue.text=Base on Sale Value
+lblEquipContractSaleValue.tooltip=PLACEHOLDER
+lblEquipPercent.text=Combat Unit %
+lblEquipPercent.tooltip=PLACEHOLDER
+lblDropShipPercent.text=DropShip %
+lblDropShipPercent.tooltip=PLACEHOLDER
+lblJumpShipPercent.text=JumpShip Percent
+lblJumpShipPercent.tooltip=PLACEHOLDER
+lblWarShipPercent.text=WarShip Percent
+lblWarShipPercent.tooltip=PLACEHOLDER
+lblContractPersonnel.text=Payroll Influences Pay
+lblContractPersonnel.tooltip=PLACEHOLDER
+lblBLCSaleValue.text=Battle Loss Compensation uses Sale Value
+lblBLCSaleValue.tooltip=PLACEHOLDER
+lblUseInfantryDoseNotCountBox.text=Infantry Not Counted Towards Contract Pay
+lblUseInfantryDoseNotCountBox.tooltip=PLACEHOLDER
+lblMercSizeLimited.text=Mercenary Campaign Size Impacts Pay
+lblMercSizeLimited.tooltip=PLACEHOLDER
+lblOverageRepaymentInFinalPayment.text=Repay Salvage Overages on Contract End
+lblOverageRepaymentInFinalPayment.tooltip=PLACEHOLDER
+
+# Markets Tab
+rulesetsContentTabs.title=Custom Rulesets
+
+stratConGeneralTab.title=General
+stratConGeneralTab.border="Strategy is just a fancy way of saying, 'I'm going to send you in first\
+ \ and see what happens.'"\
+
- Sergeant Milo "Wildcard" Trent, Raven's Fury Mercenaries
+
+legacyTab.title=Legacy Options
+legacyTab.border="In the end, your legacy is the sum of every decision you made in the cockpit. What\
+ \ you fought for and who you stood beside is what remains."\
+
- Colonel Elias "Warhound" Drake, Jade Falcon Guard
+
+# substantializeUniversalOptions
+lblSkillLevel.text=Difficulty
+lblSkillLevel.tooltip=PLACEHOLDER
+lblOpForLanceTypeMeks.text=Meks
+lblOpForLanceTypeMeks.tooltip=PLACEHOLDER
+lblOpForLanceTypeMixed.text=Mixed
+lblOpForLanceTypeMixed.tooltip=PLACEHOLDER
+lblOpForLanceTypeVehicle.text=Vehicles
+lblOpForLanceTypeVehicle.tooltip=PLACEHOLDER
+lblUseDropShips.text=Use Player DropShips
+lblUseDropShips.tooltip=PLACEHOLDER
+lblOpForUsesVTOLs.text=Enable OpFor VTOLs
+lblOpForUsesVTOLs.tooltip=PLACEHOLDER
+lblClanVehicles.text=Enable Clan Vehicles
+lblClanVehicles.tooltip=PLACEHOLDER
+lblRegionalMekVariations.text=Faction Influences Mek Weights
+lblRegionalMekVariations.tooltip=PLACEHOLDER
+lblAttachedPlayerCamouflage.text=Attached Units use Campaign Camouflage
+lblAttachedPlayerCamouflage.tooltip=PLACEHOLDER
+lblPlayerControlsAttachedUnits.text=Player Controls Attached Units
+lblPlayerControlsAttachedUnits.tooltip=PLACEHOLDER
+lblSPAUpgradeIntensity.text=SPA Chance
+lblSPAUpgradeIntensity.tooltip=PLACEHOLDER
+lblAutoConfigMunitions.text=OpFor Equip Special Munitions
+lblAutoConfigMunitions.tooltip=PLACEHOLDER
+lblScenarioModMax.text=Maximum Count
+lblScenarioModMax.tooltip=PLACEHOLDER
+lblScenarioModChance.text=Chance
+lblScenarioModChance.tooltip=PLACEHOLDER
+lblScenarioModBV.text=Battle Value Percent
+lblScenarioModBV.tooltip=PLACEHOLDER
+lblUseWeatherConditions.text=Enable Weather Conditions
+lblUseWeatherConditions.tooltip=PLACEHOLDER
+lblUseLightConditions.text=Enable Light Conditions
+lblUseLightConditions.tooltip=PLACEHOLDER
+lblUsePlanetaryConditions.text=Enable Planetary Conditions
+lblUsePlanetaryConditions.tooltip=PLACEHOLDER
+lblFixedMapChance.text=User-Made Map Chance
+lblFixedMapChance.tooltip=PLACEHOLDER
+lblRestrictPartsByMission.text=Missions Influence Availability
+lblRestrictPartsByMission.tooltip=PLACEHOLDER
+lblBonusPartExchangeValue.text=Enable Bonus Part Exchange
+lblBonusPartExchangeValue.tooltip=PLACEHOLDER
+lblBonusPartMaxExchangeCount.text=Exchange Maximum
+lblBonusPartMaxExchangeCount.tooltip=PLACEHOLDER
+lblLimitLanceWeight.text=Limit Player Drop Weights
+lblLimitLanceWeight.tooltip=PLACEHOLDER
+lblLimitLanceNumUnits.text=Limit Player Drop Sizes
+lblLimitLanceNumUnits.tooltip=PLACEHOLDER
+lblUseStrategy.text=Commander Strategy Influences Lance Counts
+lblUseStrategy.tooltip=PLACEHOLDER
+lblBaseStrategyDeployment.text=Base Force Count
+lblBaseStrategyDeployment.tooltip=PLACEHOLDER
+lblAdditionalStrategyDeployment.text=Per Rank in Strategy
+lblAdditionalStrategyDeployment.tooltip=PLACEHOLDER
+lblAdjustPaymentForStrategy.text=Adjust Contract Pay by Maximum Force Count
+lblAdjustPaymentForStrategy.tooltip=PLACEHOLDER
+
+# createUniversalScenarioGenerationPanel
+lblUniversalScenarioGenerationPanel.text=Scenario Generation
+
+# createUniversalUnitRatioPanel
+lblUniversalUnitRatioPanel.text=Unit Ratios
+
+# createUniversalModifiersPanel
+lblUniversalModifiersPanel.text=Random Modifiers
+
+# createUniversalMapGenerationPanel
+lblUniversalMapGenerationPanel.text=Map Generation
+
+# createUniversalPartsPanel
+lblUniversalPartsPanel.text=Parts Availability
+
+# createUniversalLancePanel
+lblUniversalLancePanel.text=Force Organization
+
+# createStratConTab
+lblStratConTab.text=General Options
+lblStratConTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseStratCon.text=Enable StratCon
+lblUseStratCon.tooltip=PLACEHOLDER
+lblUseGenericBattleValue.text=Enable Force Generation 3
+lblUseGenericBattleValue.tooltip=PLACEHOLDER
+lblUseVerboseBidding.text=Enable Verbose Clan Bidding
+lblUseVerboseBidding.tooltip=PLACEHOLDER
+
+# initializeLegacyTab
+lblLegacyTab.text=Legacy Options
+lblLegacyTabBody.text=Lorem ipsum odor amet, consectetuer adipiscing elit. Euismod\
+ \ varius congue rhoncus netus nostra tortor varius mi. Consequat in nunc turpis cras eget nam\
+ \ maximus. Morbigravida laoreet auctor consequat porta ex donec habitasse. Lacinia quis placerat\
+ \ turpis semper morbi blandit sapien a. Duis netus nibh cras malesuada libero; bibendum hac. Gravida\
+ \ primis vivamus est pulvinar ut? Amet nostra ante a facilisis integer mus ad nisl. Semper proin\
+ \ porttitor dis taciti phasellus, quisque massa. Facilisi rutrum nulla magnis cubilia at est nullam
+lblUseAtB.text=Enable AtB (Deprecated)
+lblUseAtB.tooltip=PLACEHOLDER
+
+# createLegacyOpForGenerationPanel
+lblLegacyOpForGenerationPanel.text=Force Generation
+lblUseVehicles.text=Enable NPC Vehicles
+lblUseVehicles.tooltip=PLACEHOLDER
+lblDoubleVehicles.text=Double NPC Vehicles
+lblDoubleVehicles.tooltip=PLACEHOLDER
+lblOpForUsesAero.text=Enable NPC Aerospace Fighters
+lblOpForUsesAero.tooltip=PLACEHOLDER
+lblOpForAeroChance.text=Aerospace Chance
+lblOpForAeroChance.tooltip=PLACEHOLDER
+lblOpForUsesLocalForces.text=Enable NPC Infantry & Turrets
+lblOpForUsesLocalForces.tooltip=PLACEHOLDER
+lblAdjustPlayerVehicles.text=Treat Player Vehicles as Half Weight
+lblAdjustPlayerVehicles.tooltip=PLACEHOLDER
+
+# createLegacyScenarioGenerationPanel
+lblLegacyScenarioGenerationPanel.text=Scenario Generation
+lblGenerateChases.text=Generate Chase Scenarios
+lblGenerateChases.tooltip=PLACEHOLDER
+lblAtBBattleIntensity.text=Battle Frequency
+lblAtBBattleIntensity.tooltip=PLACEHOLDER
+lblIntensityUpdate.text=Update Battle Frequency
+lblIntensityUpdate.tooltip=PLACEHOLDER
\ No newline at end of file
diff --git a/MekHQ/src/mekhq/Utilities.java b/MekHQ/src/mekhq/Utilities.java
index 1e4899d9fe..9d51de0166 100644
--- a/MekHQ/src/mekhq/Utilities.java
+++ b/MekHQ/src/mekhq/Utilities.java
@@ -32,7 +32,7 @@
import megamek.common.options.OptionsConstants;
import megamek.logging.MMLogger;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.finances.Money;
import mekhq.campaign.mission.IPlayerSettings;
import mekhq.campaign.personnel.Person;
diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java
index d973bf3aa0..e79ca06322 100644
--- a/MekHQ/src/mekhq/campaign/Campaign.java
+++ b/MekHQ/src/mekhq/campaign/Campaign.java
@@ -47,6 +47,7 @@
import mekhq.Utilities;
import mekhq.campaign.Quartermaster.PartAcquisitionResult;
import mekhq.campaign.againstTheBot.AtBConfiguration;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.*;
import mekhq.campaign.finances.*;
import mekhq.campaign.finances.enums.TransactionType;
diff --git a/MekHQ/src/mekhq/campaign/Quartermaster.java b/MekHQ/src/mekhq/campaign/Quartermaster.java
index f0b6e9d378..44e596f15b 100644
--- a/MekHQ/src/mekhq/campaign/Quartermaster.java
+++ b/MekHQ/src/mekhq/campaign/Quartermaster.java
@@ -23,6 +23,7 @@
import megamek.common.annotations.Nullable;
import megamek.common.weapons.infantry.InfantryWeapon;
import mekhq.MekHQ;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.PartArrivedEvent;
import mekhq.campaign.event.PartChangedEvent;
import mekhq.campaign.finances.Money;
diff --git a/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java b/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java
index 3dc85adc99..df8b3ad314 100644
--- a/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java
+++ b/MekHQ/src/mekhq/campaign/RandomSkillPreferences.java
@@ -20,15 +20,15 @@
*/
package mekhq.campaign;
-import java.io.PrintWriter;
-
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
import megamek.Version;
import megamek.logging.MMLogger;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.utilities.MHQXMLUtility;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.PrintWriter;
/**
* @author Jay Lawson
diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/campaignOptions/CampaignOptions.java
similarity index 99%
rename from MekHQ/src/mekhq/campaign/CampaignOptions.java
rename to MekHQ/src/mekhq/campaign/campaignOptions/CampaignOptions.java
index a8f2769c36..70ea35e11e 100644
--- a/MekHQ/src/mekhq/campaign/CampaignOptions.java
+++ b/MekHQ/src/mekhq/campaign/campaignOptions/CampaignOptions.java
@@ -17,7 +17,7 @@
* You should have received a copy of the GNU General Public License
* along with MekHQ. If not, see .
*/
-package mekhq.campaign;
+package mekhq.campaign.campaignOptions;
import megamek.Version;
import megamek.codeUtilities.MathUtility;
@@ -27,6 +27,7 @@
import megamek.logging.MMLogger;
import mekhq.MekHQ;
import mekhq.Utilities;
+import mekhq.campaign.RandomOriginOptions;
import mekhq.campaign.enums.PlanetaryAcquisitionFactionLimit;
import mekhq.campaign.finances.Money;
import mekhq.campaign.finances.enums.FinancialYearDuration;
@@ -4274,18 +4275,22 @@ public void setUseStratCon(final boolean useStratCon) {
this.useStratCon = useStratCon;
}
+ @Deprecated
public boolean isUseAero() {
- return useAero;
+ return true;
}
+ @Deprecated
public void setUseAero(final boolean useAero) {
this.useAero = useAero;
}
+ @Deprecated
public boolean isUseVehicles() {
- return useVehicles;
+ return true;
}
+ @Deprecated
public void setUseVehicles(final boolean useVehicles) {
this.useVehicles = useVehicles;
}
diff --git a/MekHQ/src/mekhq/campaign/CampaignPreset.java b/MekHQ/src/mekhq/campaign/campaignOptions/CampaignPreset.java
similarity index 99%
rename from MekHQ/src/mekhq/campaign/CampaignPreset.java
rename to MekHQ/src/mekhq/campaign/campaignOptions/CampaignPreset.java
index cf58104fc4..e215594869 100644
--- a/MekHQ/src/mekhq/campaign/CampaignPreset.java
+++ b/MekHQ/src/mekhq/campaign/campaignOptions/CampaignPreset.java
@@ -26,6 +26,7 @@
import megamek.utilities.xml.MMXMLUtility;
import mekhq.MHQConstants;
import mekhq.MekHQ;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.OptionsChangedEvent;
import mekhq.campaign.personnel.PersonnelOptions;
import mekhq.campaign.personnel.SkillType;
diff --git a/MekHQ/src/mekhq/campaign/event/OptionsChangedEvent.java b/MekHQ/src/mekhq/campaign/event/OptionsChangedEvent.java
index d1058415b3..c68ed38ac6 100644
--- a/MekHQ/src/mekhq/campaign/event/OptionsChangedEvent.java
+++ b/MekHQ/src/mekhq/campaign/event/OptionsChangedEvent.java
@@ -18,10 +18,10 @@
*/
package mekhq.campaign.event;
-import java.util.Objects;
-
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
+
+import java.util.Objects;
/**
* An event thrown after the campaign options were changed. The event handlers aren't supposed
diff --git a/MekHQ/src/mekhq/campaign/finances/Accountant.java b/MekHQ/src/mekhq/campaign/finances/Accountant.java
index f436fe7d50..08f55681ea 100644
--- a/MekHQ/src/mekhq/campaign/finances/Accountant.java
+++ b/MekHQ/src/mekhq/campaign/finances/Accountant.java
@@ -20,17 +20,17 @@
*/
package mekhq.campaign.finances;
-import java.util.UUID;
-
import megamek.common.Entity;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.Hangar;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.parts.Part;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.campaign.unit.Unit;
+import java.util.UUID;
+
/**
* Provides accounting for a Campaign.
*/
diff --git a/MekHQ/src/mekhq/campaign/finances/FinancialReport.java b/MekHQ/src/mekhq/campaign/finances/FinancialReport.java
index 8446e18d28..1c57ad8669 100644
--- a/MekHQ/src/mekhq/campaign/finances/FinancialReport.java
+++ b/MekHQ/src/mekhq/campaign/finances/FinancialReport.java
@@ -20,7 +20,7 @@
import megamek.common.*;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.mission.Contract;
import java.util.stream.Collectors;
diff --git a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java
index e9ddb64378..a3cf3ca49d 100644
--- a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java
+++ b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java
@@ -33,14 +33,15 @@
import mekhq.Utilities;
import mekhq.campaign.*;
import mekhq.campaign.againstTheBot.AtBConfiguration;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.finances.Finances;
import mekhq.campaign.force.Force;
import mekhq.campaign.force.Lance;
import mekhq.campaign.icons.UnitIcon;
-import mekhq.campaign.market.contractMarket.AbstractContractMarket;
-import mekhq.campaign.market.contractMarket.AtbMonthlyContractMarket;
import mekhq.campaign.market.PersonnelMarket;
import mekhq.campaign.market.ShoppingList;
+import mekhq.campaign.market.contractMarket.AbstractContractMarket;
+import mekhq.campaign.market.contractMarket.AtbMonthlyContractMarket;
import mekhq.campaign.mission.AtBContract;
import mekhq.campaign.mission.Mission;
import mekhq.campaign.mission.Scenario;
diff --git a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java
index 534fd6ca72..e28707b767 100644
--- a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java
+++ b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java
@@ -36,8 +36,8 @@
import mekhq.MHQConstants;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.againstTheBot.AtBConfiguration;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.force.Force;
import mekhq.campaign.mission.AtBDynamicScenario.BenchedEntityData;
import mekhq.campaign.mission.ScenarioForceTemplate.ForceAlignment;
diff --git a/MekHQ/src/mekhq/campaign/personnel/Award.java b/MekHQ/src/mekhq/campaign/personnel/Award.java
index 00a6df5a5c..1a5a41a02d 100644
--- a/MekHQ/src/mekhq/campaign/personnel/Award.java
+++ b/MekHQ/src/mekhq/campaign/personnel/Award.java
@@ -23,7 +23,7 @@
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import mekhq.MekHQ;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.utilities.MHQXMLUtility;
import java.io.PrintWriter;
diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java
index 934c25bc0a..25a901207c 100644
--- a/MekHQ/src/mekhq/campaign/personnel/Person.java
+++ b/MekHQ/src/mekhq/campaign/personnel/Person.java
@@ -35,8 +35,8 @@
import mekhq.MekHQ;
import mekhq.Utilities;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.ExtraData;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.PersonChangedEvent;
import mekhq.campaign.event.PersonStatusChangedEvent;
import mekhq.campaign.finances.Money;
diff --git a/MekHQ/src/mekhq/campaign/personnel/SpecialAbility.java b/MekHQ/src/mekhq/campaign/personnel/SpecialAbility.java
index 9d1bf878fe..03fe8c9f17 100644
--- a/MekHQ/src/mekhq/campaign/personnel/SpecialAbility.java
+++ b/MekHQ/src/mekhq/campaign/personnel/SpecialAbility.java
@@ -53,7 +53,7 @@
import megamek.common.weapons.infantry.InfantryWeapon;
import megamek.logging.MMLogger;
import mekhq.Utilities;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.utilities.MHQXMLUtility;
diff --git a/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java
index 5da721ba6a..e9b21793c1 100644
--- a/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java
+++ b/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java
@@ -26,7 +26,7 @@
import mekhq.MHQConstants;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.enums.AgeGroup;
import mekhq.campaign.personnel.enums.PersonnelStatus;
diff --git a/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java
index 4f9f59315a..5c999f1c78 100644
--- a/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java
+++ b/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java
@@ -20,7 +20,7 @@
import megamek.common.Compute;
import megamek.common.enums.Gender;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomDeathMethod;
import mekhq.campaign.personnel.enums.TenYearAgeRange;
diff --git a/MekHQ/src/mekhq/campaign/personnel/death/DisabledRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/DisabledRandomDeath.java
index d201319798..e4eaa438d4 100644
--- a/MekHQ/src/mekhq/campaign/personnel/death/DisabledRandomDeath.java
+++ b/MekHQ/src/mekhq/campaign/personnel/death/DisabledRandomDeath.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.death;
import megamek.common.enums.Gender;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomDeathMethod;
public class DisabledRandomDeath extends AbstractDeath {
diff --git a/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java
index a3a65ce270..ef8c8b8f05 100644
--- a/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java
+++ b/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java
@@ -20,7 +20,7 @@
import megamek.common.Compute;
import megamek.common.enums.Gender;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomDeathMethod;
public class ExponentialRandomDeath extends AbstractDeath {
diff --git a/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java
index e097f00668..8b3130d8ac 100644
--- a/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java
+++ b/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java
@@ -20,7 +20,7 @@
import megamek.common.Compute;
import megamek.common.enums.Gender;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomDeathMethod;
public class PercentageRandomDeath extends AbstractDeath {
diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java
index 1d4642f854..fe0b053b23 100644
--- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java
+++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java
@@ -22,7 +22,7 @@
import megamek.common.annotations.Nullable;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.PersonChangedEvent;
import mekhq.campaign.log.PersonalLogger;
import mekhq.campaign.personnel.Person;
diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java
index f24ea6d52f..9149e87d58 100644
--- a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java
+++ b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java
@@ -18,7 +18,7 @@
*/
package mekhq.campaign.personnel.divorce;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomDivorceMethod;
public class DisabledRandomDivorce extends AbstractDivorce {
diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java
index 5226acc6c6..d221b8a647 100644
--- a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java
+++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.divorce;
import megamek.common.Compute;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomDivorceMethod;
/**
diff --git a/MekHQ/src/mekhq/campaign/personnel/education/EducationController.java b/MekHQ/src/mekhq/campaign/personnel/education/EducationController.java
index cc4fc58969..b4f5d69099 100644
--- a/MekHQ/src/mekhq/campaign/personnel/education/EducationController.java
+++ b/MekHQ/src/mekhq/campaign/personnel/education/EducationController.java
@@ -22,7 +22,7 @@
import megamek.logging.MMLogger;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.PersonChangedEvent;
import mekhq.campaign.finances.Money;
import mekhq.campaign.finances.enums.TransactionType;
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDeathMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDeathMethod.java
index 7de03f69d3..36e6e55331 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDeathMethod.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDeathMethod.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.enums;
import mekhq.MekHQ;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.death.*;
import java.util.ResourceBundle;
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java
index c6b8551afe..8134bed03f 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.enums;
import mekhq.MekHQ;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.divorce.AbstractDivorce;
import mekhq.campaign.personnel.divorce.DisabledRandomDivorce;
import mekhq.campaign.personnel.divorce.RandomDivorce;
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java
index aa9bd9d8dc..f632ac3c59 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.enums;
import mekhq.MekHQ;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.marriage.AbstractMarriage;
import mekhq.campaign.personnel.marriage.DisabledRandomMarriage;
import mekhq.campaign.personnel.marriage.RandomMarriage;
diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java
index 8d19f7ab31..a5e012789d 100644
--- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java
+++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.enums;
import mekhq.MekHQ;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.procreation.AbstractProcreation;
import mekhq.campaign.personnel.procreation.DisabledRandomProcreation;
import mekhq.campaign.personnel.procreation.RandomProcreation;
diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java
index 3f5ef99913..97560991f9 100644
--- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java
+++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java
@@ -24,7 +24,7 @@
import megamek.common.enums.Gender;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.PersonChangedEvent;
import mekhq.campaign.log.PersonalLogger;
import mekhq.campaign.personnel.Person;
diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java
index c54825bffd..0ab5f301f3 100644
--- a/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java
+++ b/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java
@@ -18,7 +18,7 @@
*/
package mekhq.campaign.personnel.marriage;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomMarriageMethod;
public class DisabledRandomMarriage extends AbstractMarriage {
diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java
index dbb82764c0..ecafca563e 100644
--- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java
+++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.marriage;
import megamek.common.Compute;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.enums.RandomMarriageMethod;
/**
diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java
index 7d2794d92e..52f158e69b 100644
--- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java
+++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java
@@ -26,9 +26,9 @@
import mekhq.MHQConstants;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.ExtraData.IntKey;
import mekhq.campaign.ExtraData.StringKey;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.log.MedicalLogger;
import mekhq.campaign.log.PersonalLogger;
import mekhq.campaign.personnel.Person;
diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java
index 0c3cb78e9e..769706c8cc 100644
--- a/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java
+++ b/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java
@@ -18,7 +18,7 @@
*/
package mekhq.campaign.personnel.procreation;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.enums.RandomProcreationMethod;
diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java
index 8a30e6ecc2..716c135b1e 100644
--- a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java
+++ b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java
@@ -19,7 +19,7 @@
package mekhq.campaign.personnel.procreation;
import megamek.common.Compute;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.enums.RandomProcreationMethod;
diff --git a/MekHQ/src/mekhq/campaign/rating/CamOpsReputation/CommandRating.java b/MekHQ/src/mekhq/campaign/rating/CamOpsReputation/CommandRating.java
index d9f22a4ee6..8ac67aae52 100644
--- a/MekHQ/src/mekhq/campaign/rating/CamOpsReputation/CommandRating.java
+++ b/MekHQ/src/mekhq/campaign/rating/CamOpsReputation/CommandRating.java
@@ -18,13 +18,9 @@
*/
package mekhq.campaign.rating.CamOpsReputation;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
-
import megamek.logging.MMLogger;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.SkillType;
import mekhq.campaign.personnel.randomEvents.enums.personalities.Aggression;
@@ -32,6 +28,10 @@
import mekhq.campaign.personnel.randomEvents.enums.personalities.Greed;
import mekhq.campaign.personnel.randomEvents.enums.personalities.Social;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
public class CommandRating {
private static final MMLogger logger = MMLogger.create(CommandRating.class);
diff --git a/MekHQ/src/mekhq/campaign/universe/Planet.java b/MekHQ/src/mekhq/campaign/universe/Planet.java
index bc701e358d..fe435760c0 100644
--- a/MekHQ/src/mekhq/campaign/universe/Planet.java
+++ b/MekHQ/src/mekhq/campaign/universe/Planet.java
@@ -19,16 +19,9 @@
*/
package mekhq.campaign.universe;
-import java.time.LocalDate;
-import java.util.*;
-
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
-import jakarta.xml.bind.annotation.XmlAccessType;
-import jakarta.xml.bind.annotation.XmlAccessorType;
-import jakarta.xml.bind.annotation.XmlElement;
-import jakarta.xml.bind.annotation.XmlRootElement;
-import jakarta.xml.bind.annotation.XmlTransient;
+import jakarta.xml.bind.annotation.*;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import megamek.codeUtilities.ObjectUtility;
import megamek.common.EquipmentType;
@@ -36,18 +29,13 @@
import megamek.common.TargetRoll;
import megamek.logging.MMLogger;
import mekhq.Utilities;
-import mekhq.adapter.AtmosphereAdapter;
-import mekhq.adapter.BooleanValueAdapter;
-import mekhq.adapter.ClimateAdapter;
-import mekhq.adapter.DateAdapter;
-import mekhq.adapter.HPGRatingAdapter;
-import mekhq.adapter.LifeFormAdapter;
-import mekhq.adapter.PressureAdapter;
-import mekhq.adapter.SocioIndustrialDataAdapter;
-import mekhq.adapter.StringListAdapter;
-import mekhq.campaign.CampaignOptions;
+import mekhq.adapter.*;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.universe.Faction.Tag;
+import java.time.LocalDate;
+import java.util.*;
+
/**
* This is the start of a planet object that will keep lots of information about
* planets that can be displayed on the interstellar map.
diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java
index e570d55a8a..d6b25e597d 100644
--- a/MekHQ/src/mekhq/gui/CampaignGUI.java
+++ b/MekHQ/src/mekhq/gui/CampaignGUI.java
@@ -39,8 +39,8 @@
import mekhq.*;
import mekhq.campaign.Campaign;
import mekhq.campaign.CampaignController;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.CampaignPreset;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.*;
import mekhq.campaign.finances.Money;
import mekhq.campaign.finances.financialInstitutions.FinancialInstitutions;
diff --git a/MekHQ/src/mekhq/gui/CampaignGuiTab.java b/MekHQ/src/mekhq/gui/CampaignGuiTab.java
index 07777ad8b7..517882907c 100644
--- a/MekHQ/src/mekhq/gui/CampaignGuiTab.java
+++ b/MekHQ/src/mekhq/gui/CampaignGuiTab.java
@@ -18,15 +18,14 @@
*/
package mekhq.gui;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-
import mekhq.IconPackage;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.gui.enums.MHQTabType;
+import javax.swing.*;
+
/**
* Abstract base class for CampaignGUI tab components. Custom tabs should extend
* CustomCampaignGuiTab instead of this one.
diff --git a/MekHQ/src/mekhq/gui/CommandCenterTab.java b/MekHQ/src/mekhq/gui/CommandCenterTab.java
index ab303b19bf..7fe509920c 100644
--- a/MekHQ/src/mekhq/gui/CommandCenterTab.java
+++ b/MekHQ/src/mekhq/gui/CommandCenterTab.java
@@ -25,8 +25,8 @@
import mekhq.MHQOptionsChangedEvent;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.CampaignSummary;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.*;
import mekhq.campaign.finances.FinancialReport;
import mekhq.campaign.mission.Mission;
diff --git a/MekHQ/src/mekhq/gui/FileDialogs.java b/MekHQ/src/mekhq/gui/FileDialogs.java
index 873f9f325e..2dd555c8dd 100644
--- a/MekHQ/src/mekhq/gui/FileDialogs.java
+++ b/MekHQ/src/mekhq/gui/FileDialogs.java
@@ -18,20 +18,19 @@
*/
package mekhq.gui;
-import java.io.File;
-import java.time.format.DateTimeFormatter;
-import java.util.Optional;
-
-import javax.swing.JFrame;
-
-import mekhq.MekHQ;
import mekhq.MHQConstants;
+import mekhq.MekHQ;
import mekhq.campaign.Campaign;
import mekhq.campaign.CampaignPreset;
import mekhq.campaign.mission.Scenario;
import mekhq.campaign.mission.ScenarioTemplate;
import mekhq.io.FileType;
+import javax.swing.*;
+import java.io.File;
+import java.time.format.DateTimeFormatter;
+import java.util.Optional;
+
/**
* Utility class with methods to show the various open/save file dialogs
*/
diff --git a/MekHQ/src/mekhq/gui/dialog/CampaignOptionsDialog.java b/MekHQ/src/mekhq/gui/dialog/CampaignOptionsDialog.java
index 899912d1f0..b25f1f8858 100644
--- a/MekHQ/src/mekhq/gui/dialog/CampaignOptionsDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/CampaignOptionsDialog.java
@@ -27,8 +27,8 @@
import mekhq.campaign.CampaignPreset;
import mekhq.gui.FileDialogs;
import mekhq.gui.baseComponents.AbstractMHQValidationButtonDialog;
-import mekhq.gui.panes.CampaignOptionsPane;
import mekhq.gui.panes.campaignOptions.SelectPresetDialog;
+import mekhq.gui.panes.campaignOptions.tabs.CampaignOptionsPane;
import javax.swing.*;
import java.awt.*;
@@ -92,7 +92,7 @@ public void setCampaignOptionsPane(final CampaignOptionsPane campaignOptionsPane
//region Initialization
@Override
protected Container createCenterPane() {
- setCampaignOptionsPane(new CampaignOptionsPane(getFrame(), getCampaign(), isStartup()));
+ setCampaignOptionsPane(new CampaignOptionsPane(getFrame(), getCampaign()));
return getCampaignOptionsPane();
}
@@ -172,8 +172,8 @@ private void showStratConNotice() {
@Override
protected void finalizeInitialization() throws Exception {
- getCampaignOptionsPane().setOptions(getCampaign().getCampaignOptions(),
- getCampaign().getRandomSkillPreferences());
+// getCampaignOptionsPane().setOptions(getCampaign().getCampaignOptions(),
+// getCampaign().getRandomSkillPreferences());
super.finalizeInitialization();
}
//endregion Initialization
@@ -181,19 +181,20 @@ protected void finalizeInitialization() throws Exception {
//region Button Actions
@Override
protected void okAction() {
- getCampaignOptionsPane().updateOptions();
+// getCampaignOptionsPane().updateOptions();
}
@Override
protected ValidationState validateAction(final boolean display) {
- return getCampaignOptionsPane().validateOptions(display);
+// return getCampaignOptionsPane().validateOptions(display);
+ return null;
}
private void btnSaveActionPerformed() {
if (validateAction(true).isFailure()) {
return;
}
- getCampaignOptionsPane().updateOptions();
+// getCampaignOptionsPane().updateOptions();
setResult(DialogResult.CONFIRMED);
final CreateCampaignPresetDialog createCampaignPresetDialog
@@ -214,6 +215,6 @@ private void btnSaveActionPerformed() {
//endregion Button Actions
public void applyPreset(final @Nullable CampaignPreset preset) {
- getCampaignOptionsPane().applyPreset(preset);
+// getCampaignOptionsPane().applyPreset(preset);
}
}
diff --git a/MekHQ/src/mekhq/gui/dialog/CampaignPresetSelectionDialog.java b/MekHQ/src/mekhq/gui/dialog/CampaignPresetSelectionDialog.java
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/MekHQ/src/mekhq/gui/dialog/CreateCampaignPresetDialog.java b/MekHQ/src/mekhq/gui/dialog/CreateCampaignPresetDialog.java
index 0697cd47ed..6560bb5288 100644
--- a/MekHQ/src/mekhq/gui/dialog/CreateCampaignPresetDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/CreateCampaignPresetDialog.java
@@ -30,9 +30,9 @@
import megamek.common.util.sorter.NaturalOrderComparator;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.CampaignPreset;
import mekhq.campaign.RandomSkillPreferences;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.personnel.SkillType;
import mekhq.campaign.personnel.SpecialAbility;
import mekhq.campaign.personnel.ranks.RankSystem;
@@ -47,6 +47,7 @@
import mekhq.gui.displayWrappers.FactionDisplay;
import javax.swing.*;
+import javax.swing.GroupLayout.Alignment;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
@@ -538,32 +539,32 @@ public Component getListCellRendererComponent(final JList> list, final Object
layout.setVerticalGroup(
layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(getChkSpecifyDate())
- .addComponent(btnDate, GroupLayout.Alignment.LEADING))
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(btnDate, Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(getChkSpecifyFaction())
- .addComponent(getComboFaction(), GroupLayout.Alignment.LEADING))
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(getComboFaction(), Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(getChkSpecifyPlanet())
- .addComponent(getChkStartingSystemFactionSpecific(), GroupLayout.Alignment.LEADING))
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(getChkStartingSystemFactionSpecific(), Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(getComboStartingSystem())
- .addComponent(getComboStartingPlanet(), GroupLayout.Alignment.LEADING))
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(getComboStartingPlanet(), Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(getChkSpecifyRankSystem())
- .addComponent(getComboRankSystem(), GroupLayout.Alignment.LEADING))
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(getComboRankSystem(), Alignment.LEADING))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(lblContractCount)
- .addComponent(getSpnContractCount(), GroupLayout.Alignment.LEADING))
+ .addComponent(getSpnContractCount(), Alignment.LEADING))
.addComponent(getChkGM())
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(getChkSpecifyCompanyGenerationOptions())
- .addComponent(btnCompanyGenerationOptions, GroupLayout.Alignment.LEADING))
+ .addComponent(btnCompanyGenerationOptions, Alignment.LEADING))
);
layout.setHorizontalGroup(
- layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ layout.createParallelGroup(Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(getChkSpecifyDate())
.addComponent(btnDate))
@@ -623,14 +624,14 @@ private JPanel createContinuousPanel() {
layout.setVerticalGroup(
layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(getChkSpecifyGameOptions())
- .addComponent(btnGameOptions, GroupLayout.Alignment.LEADING))
+ .addComponent(btnGameOptions, Alignment.LEADING))
.addComponent(getChkSpecifyCampaignOptions())
);
layout.setHorizontalGroup(
- layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ layout.createParallelGroup(Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(getChkSpecifyGameOptions())
.addComponent(btnGameOptions))
diff --git a/MekHQ/src/mekhq/gui/dialog/MRMSDialog.java b/MekHQ/src/mekhq/gui/dialog/MRMSDialog.java
index 680e61d88d..c7e5a1a60b 100644
--- a/MekHQ/src/mekhq/gui/dialog/MRMSDialog.java
+++ b/MekHQ/src/mekhq/gui/dialog/MRMSDialog.java
@@ -18,33 +18,12 @@
*/
package mekhq.gui.dialog;
-import java.awt.BorderLayout;
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.ResourceBundle;
-
-import javax.swing.*;
-import javax.swing.JSpinner.DefaultEditor;
-import javax.swing.table.TableColumn;
-import javax.swing.table.TableRowSorter;
-
import megamek.client.ui.models.XTableColumnModel;
import megamek.client.ui.preferences.JWindowPreference;
import megamek.client.ui.preferences.PreferencesNode;
import megamek.logging.MMLogger;
import mekhq.MekHQ;
-import mekhq.campaign.CampaignOptions;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.event.OptionsChangedEvent;
import mekhq.campaign.parts.Part;
import mekhq.campaign.parts.enums.PartRepairType;
@@ -66,6 +45,16 @@
import mekhq.service.mrms.MRMSService;
import mekhq.service.mrms.MRMSService.MRMSPartSet;
+import javax.swing.*;
+import javax.swing.JSpinner.DefaultEditor;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableRowSorter;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.*;
+
/**
* @author Kipsta
*/
diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
index 8ffa181617..4e3796f849 100644
--- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
+++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
@@ -40,9 +40,9 @@
import megamek.logging.MMLogger;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
-import mekhq.campaign.CampaignOptions;
import mekhq.campaign.CampaignPreset;
import mekhq.campaign.RandomSkillPreferences;
+import mekhq.campaign.campaignOptions.CampaignOptions;
import mekhq.campaign.enums.PlanetaryAcquisitionFactionLimit;
import mekhq.campaign.event.OptionsChangedEvent;
import mekhq.campaign.finances.enums.FinancialYearDuration;
diff --git a/MekHQ/src/mekhq/gui/panes/CampaignPresetPane.java b/MekHQ/src/mekhq/gui/panes/CampaignPresetPane.java
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/MekHQ/src/mekhq/gui/panes/RankSystemsPane.java b/MekHQ/src/mekhq/gui/panes/RankSystemsPane.java
index e890477e0c..130375b69d 100644
--- a/MekHQ/src/mekhq/gui/panes/RankSystemsPane.java
+++ b/MekHQ/src/mekhq/gui/panes/RankSystemsPane.java
@@ -18,21 +18,6 @@
*/
package mekhq.gui.panes;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.GridLayout;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.swing.*;
-import javax.swing.table.TableColumn;
-
import megamek.client.ui.baseComponents.MMButton;
import megamek.client.ui.baseComponents.MMComboBox;
import megamek.client.ui.baseComponents.SpinnerCellEditor;
@@ -53,6 +38,14 @@
import mekhq.gui.dialog.CustomRankSystemCreationDialog;
import mekhq.gui.model.RankTableModel;
+import javax.swing.*;
+import javax.swing.GroupLayout.Alignment;
+import javax.swing.table.TableColumn;
+import java.awt.*;
+import java.io.File;
+import java.util.List;
+import java.util.*;
+
public class RankSystemsPane extends AbstractMHQScrollPane {
private static final MMLogger logger = MMLogger.create(RankSystemsPane.class);
@@ -179,16 +172,6 @@ protected void initialize() {
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.NORTHWEST;
- final JTextArea txtInstructionsRanks = new JTextArea(resources.getString("txtInstructionsRanks.text"));
- txtInstructionsRanks.setBorder(BorderFactory.createCompoundBorder(
- BorderFactory.createTitledBorder(resources.getString("txtInstructionsRanks.title")),
- BorderFactory.createEmptyBorder(5, 5, 5, 5)));
- txtInstructionsRanks.setOpaque(false);
- txtInstructionsRanks.setEditable(false);
- txtInstructionsRanks.setLineWrap(true);
- txtInstructionsRanks.setWrapStyleWord(true);
- rankSystemsPanel.add(txtInstructionsRanks, gbc);
-
gbc.gridy++;
rankSystemsPanel.add(createRankSystemPanel(), gbc);
@@ -287,14 +270,14 @@ public Component getListCellRendererComponent(final JList> list, final Object
layout.setVerticalGroup(
layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(lblRankSystem)
.addComponent(getComboRankSystems())
.addComponent(getComboRankSystemType())
- .addComponent(btnCreateCustomRankSystem, GroupLayout.Alignment.LEADING)));
+ .addComponent(btnCreateCustomRankSystem, Alignment.LEADING)));
layout.setHorizontalGroup(
- layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ layout.createParallelGroup(Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblRankSystem)
.addComponent(getComboRankSystems())
diff --git a/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/BiographyTab.java b/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/BiographyTab.java
new file mode 100644
index 0000000000..ab98a2c404
--- /dev/null
+++ b/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/BiographyTab.java
@@ -0,0 +1,1210 @@
+package mekhq.gui.panes.campaignOptions.tabs;
+
+import megamek.client.generator.RandomGenderGenerator;
+import megamek.client.generator.RandomNameGenerator;
+import megamek.client.ui.baseComponents.MMComboBox;
+import megamek.common.annotations.Nullable;
+import mekhq.campaign.Campaign;
+import mekhq.campaign.personnel.enums.AgeGroup;
+import mekhq.campaign.personnel.enums.FamilialRelationshipDisplayLevel;
+import mekhq.campaign.personnel.enums.PersonnelRole;
+import mekhq.campaign.personnel.enums.RandomDeathMethod;
+import mekhq.campaign.universe.Faction;
+import mekhq.campaign.universe.Planet;
+import mekhq.campaign.universe.PlanetarySystem;
+import mekhq.gui.panes.RankSystemsPane;
+
+import javax.swing.*;
+import javax.swing.GroupLayout.Alignment;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import static mekhq.gui.panes.campaignOptions.tabs.CampaignOptionsUtilities.*;
+
+/**
+ * The `BiographyTab` class represents the biography settings tab in campaign options.
+ * It is responsible for maintaining and allowing updates to the settings related to biographies
+ * in a campaign. This includes general settings, name and portrait settings, rank settings,
+ * background settings, death settings, and education settings.
+ *
+ * Each area of settings is initialized and managed in its own tab, which allows for organization
+ * and easy navigation settings related to biographic information.
+ *
+ * The class also has a set of fields that dictate the state of the individual settings.
+ *
+ * Some of the key settings managed by this tab include:
+ * - Random XP: a setting that controls the use of Dylan's random XP.
+ * - Gender settings: a set of settings that controls the gender ratio and non-binary dice size.
+ * - Name and portrait settings: a set of settings to control the use of origin factions for names,
+ * and the behavior of random portraits.
+ * - Education settings: a set of settings to control the usage and specifics of the educational module.
+ *
+ * And many more settings are controlled within this class.
+ */
+public class BiographyTab {
+ Campaign campaign;
+ JFrame frame;
+ String name;
+
+ //start General Tab
+ private JCheckBox chkUseDylansRandomXP;
+ private JLabel lblGender;
+ private JSlider sldGender;
+ private JLabel lblNonBinaryDiceSize;
+ private JSpinner spnNonBinaryDiceSize;
+ private JLabel lblFamilyDisplayLevel;
+ private MMComboBox comboFamilyDisplayLevel;
+ private JPanel pnlAnniversariesPanel;
+ private JCheckBox chkAnnounceOfficersOnly;
+ private JCheckBox chkAnnounceBirthdays;
+ private JCheckBox chkAnnounceChildBirthdays;
+ private JCheckBox chkAnnounceRecruitmentAnniversaries;
+ //end General Tab
+
+ //start Backgrounds Tab
+ private JCheckBox chkUseRandomPersonalities;
+ private JCheckBox chkUseRandomPersonalityReputation;
+ private JCheckBox chkUseIntelligenceXpMultiplier;
+ private JCheckBox chkUseSimulatedRelationships;
+ private JPanel pnlRandomOriginOptions;
+ private JCheckBox chkRandomizeOrigin;
+ private JCheckBox chkRandomizeDependentsOrigin;
+ private JCheckBox chkRandomizeAroundSpecifiedPlanet;
+ private JCheckBox chkSpecifiedSystemFactionSpecific;
+ private JLabel lblSpecifiedSystem;
+ private MMComboBox comboSpecifiedSystem;
+ private JLabel lblSpecifiedPlanet;
+ private MMComboBox comboSpecifiedPlanet;
+ private JLabel lblOriginSearchRadius;
+ private JSpinner spnOriginSearchRadius;
+ private JLabel lblOriginDistanceScale;
+ private JSpinner spnOriginDistanceScale;
+ private JCheckBox chkAllowClanOrigins;
+ private JCheckBox chkExtraRandomOrigin;
+ //end Backgrounds Tab
+
+ //start Death Tab
+ private JCheckBox chkKeepMarriedNameUponSpouseDeath;
+ private JLabel lblRandomDeathMethod;
+ private MMComboBox comboRandomDeathMethod;
+ private JCheckBox chkUseRandomClanPersonnelDeath;
+ private JCheckBox chkUseRandomPrisonerDeath;
+ private JCheckBox chkUseRandomDeathSuicideCause;
+ private JLabel lblPercentageRandomDeathChance;
+ private JSpinner spnPercentageRandomDeathChance;
+
+ private JPanel pnlDeathAgeGroup;
+ private Map chkEnabledRandomDeathAgeGroups;
+ //end Death Tab
+
+ //start Education Tab
+ private JCheckBox chkUseEducationModule;
+ private JLabel lblCurriculumXpRate;
+ private JSpinner spnCurriculumXpRate;
+ private JLabel lblMaximumJumpCount;
+ private JSpinner spnMaximumJumpCount;
+ private JCheckBox chkUseReeducationCamps;
+ private JCheckBox chkEnableOverrideRequirements;
+ private JCheckBox chkShowIneligibleAcademies;
+ private JLabel lblEntranceExamBaseTargetNumber;
+ private JSpinner spnEntranceExamBaseTargetNumber;
+ private JLabel lblEntranceExamBaseTargetNumberPost;
+
+ private JPanel pnlEnableStandardSets;
+ private JCheckBox chkEnableLocalAcademies;
+ private JCheckBox chkEnablePrestigiousAcademies;
+ private JCheckBox chkEnableUnitEducation;
+
+ private JPanel pnlXpAndSkillBonuses;
+ private JCheckBox chkEnableBonuses;
+ private JLabel lblFacultyXpMultiplier;
+ private JSpinner spnFacultyXpMultiplier;
+
+ private JPanel pnlDropoutChance;
+ private JLabel lblAdultDropoutChance;
+ private JSpinner spnAdultDropoutChance;
+ private JLabel lblChildrenDropoutChance;
+ private JSpinner spnChildrenDropoutChance;
+
+ private JPanel pnlAccidentsAndEvents;
+ private JCheckBox chkAllAges;
+ private JLabel lblMilitaryAcademyAccidents;
+ private JSpinner spnMilitaryAcademyAccidents;
+ //end Education Tab
+
+ //start Name and Portrait Tab
+ private JCheckBox chkUseOriginFactionForNames;
+ private JLabel lblFactionNames;
+ private MMComboBox comboFactionNames;
+
+ private JPanel pnlRandomPortrait;
+ private JCheckBox[] chkUsePortrait;
+ private JCheckBox allPortraitsBox;
+ private JCheckBox noPortraitsBox;
+ private JCheckBox chkAssignPortraitOnRoleChange;
+ //end Name and Portrait Tab
+
+ //start Rank Tab
+ private RankSystemsPane rankSystemsPane;
+ //end Rank Tab
+
+ /**
+ * Initializes a new {@link BiographyTab} with the specified campaign, frame, and name.
+ *
+ * @param campaign the campaign associated with the {@link BiographyTab}
+ * @param frame the {@link JFrame} used for displaying the {@link BiographyTab}
+ * @param name the name of the {@link BiographyTab}
+ */
+ BiographyTab(Campaign campaign, JFrame frame, String name) {
+ this.campaign = campaign;
+ this.frame = frame;
+ this.name = name;
+
+ initialize();
+ }
+
+ /**
+ * Initializes the components for the NameAndPortraitTab panel.
+ * The panel contains various settings related to names and portraits.
+ */
+ private void initialize() {
+ initializeGeneralTab();
+ initializeBackgroundsTab();
+ initializeDeathTab();
+ initializeEducationTab();
+ initializeNameAndPortraitTab();
+ }
+
+ /**
+ * Initializes the components for the EducationTab panel.
+ * The panel contains various settings related to the educational module.
+ */
+ private void initializeNameAndPortraitTab() {
+ chkUseOriginFactionForNames = new JCheckBox();
+ lblFactionNames = new JLabel();
+ comboFactionNames = new MMComboBox<>("comboFactionNames", getFactionNamesModel());
+ chkAssignPortraitOnRoleChange = new JCheckBox();
+
+ pnlRandomPortrait = new JPanel();
+ chkUsePortrait = new JCheckBox[1]; // We're going to properly initialize this later
+ allPortraitsBox = new JCheckBox();
+ noPortraitsBox = new JCheckBox();
+ }
+
+ /**
+ * Initializes the components for the DeathTab panel.
+ * The panel deals with various settings related to in-game character death.
+ */
+ private void initializeEducationTab() {
+ chkUseEducationModule = new JCheckBox();
+ lblCurriculumXpRate = new JLabel();
+ spnCurriculumXpRate = new JSpinner();
+ lblMaximumJumpCount = new JLabel();
+ spnMaximumJumpCount = new JSpinner();
+ chkUseReeducationCamps = new JCheckBox();
+ chkEnableOverrideRequirements = new JCheckBox();
+ chkShowIneligibleAcademies = new JCheckBox();
+ lblEntranceExamBaseTargetNumber = new JLabel();
+ spnEntranceExamBaseTargetNumber = new JSpinner();
+ lblEntranceExamBaseTargetNumberPost = new JLabel();
+
+ pnlEnableStandardSets = new JPanel();
+ chkEnableLocalAcademies = new JCheckBox();
+ chkEnablePrestigiousAcademies = new JCheckBox();
+ chkEnableUnitEducation = new JCheckBox();
+
+ pnlXpAndSkillBonuses = new JPanel();
+ chkEnableBonuses = new JCheckBox();
+ lblFacultyXpMultiplier = new JLabel();
+ spnFacultyXpMultiplier = new JSpinner();
+
+ pnlDropoutChance = new JPanel();
+ lblAdultDropoutChance = new JLabel();
+ spnAdultDropoutChance = new JSpinner();
+ lblChildrenDropoutChance = new JLabel();
+ spnChildrenDropoutChance = new JSpinner();
+
+ pnlAccidentsAndEvents = new JPanel();
+ chkAllAges = new JCheckBox();
+ lblMilitaryAcademyAccidents = new JLabel();
+ spnMilitaryAcademyAccidents = new JSpinner();
+ }
+
+ /**
+ * Initializes the components for the BackgroundsTab panel.
+ * The panel contains various settings related to backgrounds and origins.
+ */
+ private void initializeDeathTab() {
+ chkKeepMarriedNameUponSpouseDeath = new JCheckBox();
+ lblRandomDeathMethod = new JLabel();
+ comboRandomDeathMethod = new MMComboBox<>("comboRandomDeathMethod", RandomDeathMethod.values());
+ chkUseRandomClanPersonnelDeath = new JCheckBox();
+ chkUseRandomPrisonerDeath = new JCheckBox();
+ chkUseRandomDeathSuicideCause = new JCheckBox();
+ lblPercentageRandomDeathChance = new JLabel();
+ spnPercentageRandomDeathChance = new JSpinner();
+
+ pnlDeathAgeGroup = new JPanel();
+ chkEnabledRandomDeathAgeGroups = new HashMap<>();
+ }
+
+ /**
+ * Initializes the components for the GeneralTab panel.
+ * The panel contains various general settings.
+ */
+ private void initializeBackgroundsTab() {
+ chkUseRandomPersonalities = new JCheckBox();
+ chkUseRandomPersonalityReputation = new JCheckBox();
+ chkUseIntelligenceXpMultiplier = new JCheckBox();
+ chkUseSimulatedRelationships = new JCheckBox();
+
+ pnlRandomOriginOptions = new JPanel();
+ chkRandomizeOrigin = new JCheckBox();
+ chkRandomizeDependentsOrigin = new JCheckBox();
+ chkRandomizeAroundSpecifiedPlanet = new JCheckBox();
+ chkSpecifiedSystemFactionSpecific = new JCheckBox();
+ lblSpecifiedSystem = new JLabel();
+ comboSpecifiedSystem = new MMComboBox<>("comboSpecifiedSystem");
+ lblSpecifiedPlanet = new JLabel();
+ comboSpecifiedPlanet = new MMComboBox<>("comboSpecifiedPlanet");
+ lblOriginSearchRadius = new JLabel();
+ spnOriginSearchRadius = new JSpinner();
+ lblOriginDistanceScale = new JLabel();
+ spnOriginDistanceScale = new JSpinner();
+ chkAllowClanOrigins = new JCheckBox();
+ chkExtraRandomOrigin = new JCheckBox();
+ }
+
+ /**
+ * Initializes components of the GeneralTab.
+ * The panel contains general settings.
+ */
+ private void initializeGeneralTab() {
+ chkUseDylansRandomXP = new JCheckBox();
+ lblGender = new JLabel();
+ sldGender = new JSlider();
+ lblNonBinaryDiceSize = new JLabel();
+ spnNonBinaryDiceSize = new JSpinner();
+ lblFamilyDisplayLevel = new JLabel();
+ comboFamilyDisplayLevel = new MMComboBox<>("comboFamilyDisplayLevel",
+ FamilialRelationshipDisplayLevel.values());
+
+ pnlAnniversariesPanel = new JPanel();
+ chkAnnounceOfficersOnly = new JCheckBox();
+ chkAnnounceBirthdays = new JCheckBox();
+ chkAnnounceChildBirthdays = new JCheckBox();
+ chkAnnounceRecruitmentAnniversaries = new JCheckBox();
+ }
+
+ /**
+ * Retrieves a {@link DefaultComboBoxModel} containing faction names generated by the
+ * {@link RandomNameGenerator} instance.
+ *
+ * @return DefaultComboBoxModel containing faction names
+ */
+ private static DefaultComboBoxModel getFactionNamesModel() {
+ DefaultComboBoxModel factionNamesModel = new DefaultComboBoxModel<>();
+ for (final String faction : RandomNameGenerator.getInstance().getFactions()) {
+ factionNamesModel.addElement(faction);
+ }
+ factionNamesModel.setSelectedItem(RandomNameGenerator.getInstance().getChosenFaction());
+ return factionNamesModel;
+ }
+
+ /**
+ * Creates a general tab for the Biography category containing various components
+ *
+ * @return a {@link JPanel} representing the general tab with multiple input components and panels
+ */
+ JPanel createGeneralTab() {
+ // Header
+ JPanel headerPanel = createHeaderPanel("BiographyGeneralTab",
+ getImageDirectory() + "logo_federated_suns.png",
+ true);
+
+ // Contents
+ chkUseDylansRandomXP = createCheckBox("UseDylansRandomXP");
+
+ lblGender = createLabel("Gender");
+ sldGender = new JSlider(SwingConstants.HORIZONTAL, 0, 100, RandomGenderGenerator.getPercentFemale());
+ sldGender.setMajorTickSpacing(25);
+ sldGender.setPaintTicks(true);
+ sldGender.setPaintLabels(true);
+
+ lblNonBinaryDiceSize = createLabel("NonBinaryDiceSize");
+ spnNonBinaryDiceSize = createSpinner("NonBinaryDiceSize",
+ 60, 0, 100000, 1);
+
+ lblFamilyDisplayLevel = createLabel("FamilyDisplayLevel");
+
+ pnlAnniversariesPanel = createAnniversariesPanel();
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("BiographyGeneralTab", true);
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(headerPanel)
+ .addComponent(chkUseDylansRandomXP)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblGender)
+ .addComponent(sldGender))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblNonBinaryDiceSize)
+ .addComponent(spnNonBinaryDiceSize))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblFamilyDisplayLevel)
+ .addComponent(comboFamilyDisplayLevel))
+ .addComponent(pnlAnniversariesPanel));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(headerPanel, Alignment.CENTER)
+ .addComponent(chkUseDylansRandomXP)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblGender)
+ .addComponent(sldGender))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblNonBinaryDiceSize)
+ .addComponent(spnNonBinaryDiceSize)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblFamilyDisplayLevel)
+ .addComponent(comboFamilyDisplayLevel)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addComponent(pnlAnniversariesPanel)));
+
+ // Create Parent Panel and return
+ return createParentPanel(panel, "BiographyGeneralTab");
+ }
+
+ /**
+ * @return a {@link JPanel} representing the Anniversaries panel with checkboxes for different
+ * anniversary options
+ */
+ private JPanel createAnniversariesPanel() {
+ // Contents
+ chkAnnounceBirthdays = createCheckBox("AnnounceBirthdays");
+ chkAnnounceRecruitmentAnniversaries = createCheckBox("AnnounceRecruitmentAnniversaries");
+ chkAnnounceOfficersOnly = createCheckBox("AnnounceOfficersOnly");
+ chkAnnounceChildBirthdays = createCheckBox("AnnounceChildBirthdays");
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("AnniversariesPanel", true,
+ "AnniversariesPanel");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(chkAnnounceOfficersOnly)
+ .addComponent(chkAnnounceBirthdays)
+ .addComponent(chkAnnounceChildBirthdays)
+ .addComponent(chkAnnounceRecruitmentAnniversaries));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(chkAnnounceOfficersOnly)
+ .addComponent(chkAnnounceBirthdays)
+ .addComponent(chkAnnounceChildBirthdays)
+ .addComponent(chkAnnounceRecruitmentAnniversaries)));
+
+ return panel;
+ }
+
+ /**
+ * @return a JPanel representing the Backgrounds tab with specific components like checkboxes and
+ * options panel
+ */
+ JPanel createBackgroundsTab() {
+ // Header
+ JPanel headerPanel = createHeaderPanel("BackgroundsTab",
+ getImageDirectory() + "logo_clan_goliath_scorpion.png", true);
+
+ // Contents
+ chkUseRandomPersonalities = createCheckBox("UseRandomPersonalities");
+ chkUseRandomPersonalityReputation = createCheckBox("UseRandomPersonalityReputation");
+ chkUseIntelligenceXpMultiplier = createCheckBox("UseIntelligenceXpMultiplier");
+ chkUseSimulatedRelationships = createCheckBox("UseSimulatedRelationships");
+
+ pnlRandomOriginOptions = createRandomOriginOptionsPanel();
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("BackgroundsTab", true);
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(headerPanel)
+ .addComponent(chkUseRandomPersonalities)
+ .addComponent(chkUseRandomPersonalityReputation)
+ .addComponent(chkUseIntelligenceXpMultiplier)
+ .addComponent(chkUseSimulatedRelationships)
+ .addComponent(pnlRandomOriginOptions));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(headerPanel, Alignment.CENTER)
+ .addComponent(chkUseRandomPersonalities)
+ .addComponent(chkUseRandomPersonalityReputation)
+ .addComponent(chkUseIntelligenceXpMultiplier)
+ .addComponent(chkUseSimulatedRelationships)
+ .addComponent(pnlRandomOriginOptions)));
+
+ // Create Parent Panel and return
+ return createParentPanel(panel, "BackgroundsTab");
+ }
+
+ /**
+ * Creates a panel containing options for randomizing personnel origins.
+ *
+ * @return a {@link JPanel} containing the random origin options, configured with the necessary components
+ */
+ private JPanel createRandomOriginOptionsPanel() {
+ // Contents
+ chkRandomizeOrigin = createCheckBox("RandomizeOrigin");
+ chkRandomizeDependentsOrigin = createCheckBox("RandomizeDependentsOrigin");
+ chkRandomizeAroundSpecifiedPlanet = createCheckBox("RandomizeAroundSpecifiedPlanet");
+
+ chkSpecifiedSystemFactionSpecific = createCheckBox("SpecifiedSystemFactionSpecific");
+ chkSpecifiedSystemFactionSpecific.addActionListener(evt -> {
+ final PlanetarySystem planetarySystem = comboSpecifiedSystem.getSelectedItem();
+ if ((planetarySystem == null)
+ || !planetarySystem.getFactionSet(campaign.getLocalDate()).contains(campaign.getFaction())) {
+ restoreComboSpecifiedSystem();
+ }
+ });
+
+
+ lblSpecifiedSystem = createLabel("SpecifiedSystem");
+ comboSpecifiedSystem.setRenderer(new DefaultListCellRenderer() {
+ @Override
+ 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 PlanetarySystem) {
+ setText(((PlanetarySystem) value).getName(campaign.getLocalDate()));
+ }
+ return this;
+ }
+ });
+ comboSpecifiedSystem.addActionListener(evt -> {
+ final PlanetarySystem planetarySystem = comboSpecifiedSystem.getSelectedItem();
+ final Planet planet = comboSpecifiedPlanet.getSelectedItem();
+ if ((planetarySystem == null)
+ || ((planet != null) && !planet.getParentSystem().equals(planetarySystem))) {
+ restoreComboSpecifiedPlanet();
+ }
+ });
+
+ lblSpecifiedPlanet = createLabel("SpecifiedPlanet");
+ comboSpecifiedPlanet.setRenderer(new DefaultListCellRenderer() {
+ @Override
+ 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 Planet) {
+ setText(((Planet) value).getName(campaign.getLocalDate()));
+ }
+ return this;
+ }
+ });
+
+ lblOriginSearchRadius = createLabel("OriginSearchRadius");
+ spnOriginSearchRadius = createSpinner("OriginSearchRadius",
+ 0, 0, 2000, 25);
+
+ lblOriginDistanceScale = createLabel("OriginDistanceScale");
+ spnOriginDistanceScale = createSpinner("OriginDistanceScale",
+ 0.6, 0.1, 2.0, 0.1);
+
+ chkAllowClanOrigins = createCheckBox("AllowClanOrigins");
+ chkExtraRandomOrigin = createCheckBox("ExtraRandomOrigin");
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("RandomOriginOptionsPanel", true,
+ "RandomOriginOptionsPanel");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(chkRandomizeOrigin)
+ .addComponent(chkRandomizeDependentsOrigin)
+ .addComponent(chkRandomizeAroundSpecifiedPlanet)
+ .addComponent(chkSpecifiedSystemFactionSpecific)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblSpecifiedSystem)
+ .addComponent(comboSpecifiedSystem)
+ .addComponent(lblSpecifiedPlanet)
+ .addComponent(comboSpecifiedPlanet))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblOriginSearchRadius)
+ .addComponent(spnOriginSearchRadius)
+ .addComponent(lblOriginDistanceScale)
+ .addComponent(spnOriginDistanceScale))
+ .addComponent(chkAllowClanOrigins)
+ .addComponent(chkExtraRandomOrigin));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(chkRandomizeOrigin)
+ .addComponent(chkRandomizeDependentsOrigin)
+ .addComponent(chkRandomizeAroundSpecifiedPlanet)
+ .addComponent(chkSpecifiedSystemFactionSpecific)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblSpecifiedSystem)
+ .addComponent(comboSpecifiedSystem)
+ .addComponent(lblSpecifiedPlanet)
+ .addComponent(comboSpecifiedPlanet)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblOriginSearchRadius)
+ .addComponent(spnOriginSearchRadius)
+ .addComponent(lblOriginDistanceScale)
+ .addComponent(spnOriginDistanceScale)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addComponent(chkAllowClanOrigins)
+ .addComponent(chkExtraRandomOrigin)));
+
+ return panel;
+ }
+
+ /**
+ * Restores the list of planets in the combo box based on the selected planetary system.
+ * If no planetary system is selected, clear the combo box.
+ * If a planetary system is selected, populates the combo box with the planets from that system,
+ * and selects the primary planet of the system.
+ */
+ private void restoreComboSpecifiedPlanet() {
+ final PlanetarySystem planetarySystem = comboSpecifiedSystem.getSelectedItem();
+
+ if (planetarySystem == null) {
+ comboSpecifiedPlanet.removeAllItems();
+ } else {
+ comboSpecifiedPlanet.setModel(new DefaultComboBoxModel<>(
+ planetarySystem.getPlanets().toArray(new Planet[] {})));
+ comboSpecifiedPlanet.setSelectedItem(planetarySystem.getPrimaryPlanet());
+ }
+ }
+
+ /**
+ * Removes all items from the combo box, then populates it with planetary systems
+ * based on the selected faction filter.
+ * Restores the combo box for specified planets after updating the specified system combo box.
+ */
+ private void restoreComboSpecifiedSystem() {
+ comboSpecifiedSystem.removeAllItems();
+
+ comboSpecifiedSystem.setModel(new DefaultComboBoxModel<>(getPlanetarySystems(
+ chkSpecifiedSystemFactionSpecific.isSelected() ? campaign.getFaction() : null)));
+
+ restoreComboSpecifiedPlanet();
+ }
+
+ /**
+ * Retrieves an array of {@link PlanetarySystem} objects based on the provided {@link Faction}.
+ *
+ * @param faction The {@link Faction} to filter the {@link PlanetarySystem} by. Specify null for
+ * no filtering.
+ * @return An array of {@link PlanetarySystem} objects that match the filtering criteria, sorted
+ * by system name.
+ */
+ private PlanetarySystem[] getPlanetarySystems(final @Nullable Faction faction) {
+ ArrayList systems = campaign.getSystems();
+ ArrayList filteredSystems = new ArrayList<>();
+
+ // Filter systems
+ for (PlanetarySystem planetarySystem : systems) {
+ if ((faction == null) || planetarySystem.getFactionSet(campaign.getLocalDate()).contains(faction)) {
+ filteredSystems.add(planetarySystem);
+ }
+ }
+
+ // Sort systems
+ filteredSystems.sort(Comparator.comparing(p -> p.getName(campaign.getLocalDate())));
+
+ // Convert to array
+ return filteredSystems.toArray(new PlanetarySystem[0]);
+ }
+
+ /**
+ * Creates and returns a {@link JPanel} for the Death Tab.
+ * The panel includes header, various checkboxes, labels, spinners, and a custom combo box.
+ *
+ * @return {@link JPanel} representing the Death Tab with all its components
+ */
+ JPanel createDeathTab() {
+ // Header
+ JPanel headerPanel = createHeaderPanel("DeathTab",
+ getImageDirectory() + "logo_filtvelt_coalition.png",
+ true);
+
+ // Contents
+ chkKeepMarriedNameUponSpouseDeath = createCheckBox("KeepMarriedNameUponSpouseDeath");
+
+ lblRandomDeathMethod = createLabel("RandomDeathMethod");
+ comboRandomDeathMethod.setRenderer(new DefaultListCellRenderer() {
+ @Override
+ 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 RandomDeathMethod) {
+ list.setToolTipText(((RandomDeathMethod) value).getToolTipText());
+ }
+ return this;
+ }
+ });
+
+ chkUseRandomClanPersonnelDeath = createCheckBox("UseRandomClanPersonnelDeath");
+ chkUseRandomPrisonerDeath = createCheckBox("UseRandomPrisonerDeath");
+ chkUseRandomDeathSuicideCause = createCheckBox("UseRandomDeathSuicideCause");
+
+ pnlDeathAgeGroup = createDeathAgeGroupsPanel();
+
+ lblPercentageRandomDeathChance = createLabel("PercentageRandomDeathChance");
+ spnPercentageRandomDeathChance = createSpinner("PercentageRandomDeathChance",
+ 0, 0, 100, 0.000001);
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("DeathTab", true);
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(headerPanel)
+ .addComponent(chkKeepMarriedNameUponSpouseDeath)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblRandomDeathMethod)
+ .addComponent(comboRandomDeathMethod))
+ .addComponent(chkUseRandomClanPersonnelDeath)
+ .addComponent(chkUseRandomPrisonerDeath)
+ .addComponent(chkUseRandomDeathSuicideCause)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblPercentageRandomDeathChance)
+ .addComponent(spnPercentageRandomDeathChance))
+ .addComponent(pnlDeathAgeGroup));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(headerPanel, Alignment.CENTER)
+ .addComponent(chkKeepMarriedNameUponSpouseDeath)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblRandomDeathMethod)
+ .addComponent(comboRandomDeathMethod)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addComponent(chkUseRandomClanPersonnelDeath)
+ .addComponent(chkUseRandomPrisonerDeath)
+ .addComponent(chkUseRandomDeathSuicideCause)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblPercentageRandomDeathChance)
+ .addComponent(spnPercentageRandomDeathChance)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addComponent(pnlDeathAgeGroup)));
+
+ // Create Parent Panel and return
+ return createParentPanel(panel, "DeathTab");
+ }
+
+ /**
+ * Creates a panel for the Death Age Groups tab with checkboxes for different age groups
+ *
+ * @return a {@link JPanel} representing the Death Age Groups tab with checkboxes for each age group
+ */
+ private JPanel createDeathAgeGroupsPanel() {
+ final AgeGroup[] ageGroups = AgeGroup.values();
+
+ // Create the Panel
+ final JPanel panel = createStandardPanel("DeathAgeGroupsPanel", true,
+ "DeathAgeGroupsPanel");
+ panel.setLayout(new GridLayout(1, ageGroups.length));
+
+ // Contents
+ for (final AgeGroup ageGroup : ageGroups) {
+ final JCheckBox checkBox = new JCheckBox(ageGroup.toString());
+ checkBox.setToolTipText(ageGroup.getToolTipText());
+ checkBox.setName("chk" + ageGroup);
+
+ panel.add(checkBox);
+ chkEnabledRandomDeathAgeGroups.put(ageGroup, checkBox);
+ }
+
+ return panel;
+ }
+
+ /**
+ * Constructs and configures an "Education" {@link JPanel}.
+ * The panel includes various controls related to education settings,
+ * including checkboxes for enabling specific modules and settings,
+ * spinners for configuring values such as XP rate and jump count,
+ * and separate panels for managing standard sets, XP and skill bonuses,
+ * dropout chances, accidents, and events.
+ *
+ * The JPanel configuration is done using a {@link GroupLayout}, setting up
+ * the components in a structured layout with optimized vertical and
+ * horizontal alignments.
+ *
+ * @return {@link JPanel} The newly created and configured parent JPanel for
+ * the Education tab, containing all the educational settings controls.
+ */
+ JPanel createEducationTab() {
+ // Header
+ JPanel headerPanel = createHeaderPanel("EducationTab",
+ getImageDirectory() + "logo_free_worlds_league.png",
+ true);
+
+ // Contents
+ chkUseEducationModule = createCheckBox("UseEducationModule");
+
+ lblCurriculumXpRate = createLabel("CurriculumXpRate");
+ spnCurriculumXpRate = createSpinner("CurriculumXpRate",
+ 3, 1, 10, 1);
+
+ lblMaximumJumpCount = createLabel("MaximumJumpCount");
+ spnMaximumJumpCount = createSpinner("MaximumJumpCount",
+ 5, 1, 200, 1);
+
+ chkUseReeducationCamps = createCheckBox("UseReeducationCamps");
+
+ pnlEnableStandardSets = createEnableStandardSetsPanel();
+
+ chkEnableOverrideRequirements = createCheckBox("EnableOverrideRequirements");
+
+ chkShowIneligibleAcademies = createCheckBox("ShowIneligibleAcademies");
+
+ lblEntranceExamBaseTargetNumber = createLabel("EntranceExamBaseTargetNumber");
+ spnEntranceExamBaseTargetNumber = createSpinner("EntranceExamBaseTargetNumber",
+ 14, 0, 20, 1);
+ lblEntranceExamBaseTargetNumberPost = createLabel("EntranceExamBaseTargetNumberPost");
+
+ pnlXpAndSkillBonuses = createXpAndSkillBonusesPanel();
+
+ pnlDropoutChance = createDropoutChancePanel();
+
+ pnlAccidentsAndEvents = createAccidentsAndEventsPanel();
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("EducationTab", true);
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(headerPanel)
+ .addComponent(chkUseEducationModule)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblCurriculumXpRate)
+ .addComponent(spnCurriculumXpRate)
+ .addComponent(lblMaximumJumpCount)
+ .addComponent(spnMaximumJumpCount))
+ .addComponent(chkUseReeducationCamps)
+ .addComponent(pnlEnableStandardSets)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(chkShowIneligibleAcademies)
+ .addComponent(chkEnableOverrideRequirements))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblEntranceExamBaseTargetNumber)
+ .addComponent(spnEntranceExamBaseTargetNumber)
+ .addComponent(lblEntranceExamBaseTargetNumberPost))
+ .addComponent(pnlXpAndSkillBonuses)
+ .addComponent(pnlDropoutChance)
+ .addComponent(pnlAccidentsAndEvents));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(headerPanel, Alignment.CENTER)
+ .addComponent(chkUseEducationModule)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblCurriculumXpRate)
+ .addComponent(spnCurriculumXpRate)
+ .addComponent(lblMaximumJumpCount)
+ .addComponent(spnMaximumJumpCount)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addComponent(chkUseReeducationCamps)
+ .addComponent(pnlEnableStandardSets)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(chkShowIneligibleAcademies)
+ .addComponent(chkEnableOverrideRequirements)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblEntranceExamBaseTargetNumber)
+ .addComponent(spnEntranceExamBaseTargetNumber)
+ .addComponent(lblEntranceExamBaseTargetNumberPost)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addComponent(pnlXpAndSkillBonuses)
+ .addComponent(pnlDropoutChance)
+ .addComponent(pnlAccidentsAndEvents)));
+
+ // Create Parent Panel and return
+ return createParentPanel(panel, "EducationTab");
+ }
+
+ /**
+ * Constructs and configures an "Enable Standard Sets" {@link JPanel}.
+ * The panel consists of three checkboxes: to enable local academies,
+ * prestigious academies, and unit education.
+ *
+ * A {@link GroupLayout} is used to arrange these components in an
+ * optimal manner, ensuring good readability and usability in both
+ * vertical and horizontal alignments.
+ *
+ * @return {@link JPanel} The newly constructed and configured JPanel for
+ * Enable Standard Sets settings.
+ */
+ private JPanel createEnableStandardSetsPanel() {
+ // Contents
+ chkEnableLocalAcademies = createCheckBox("EnableLocalAcademies");
+ chkEnablePrestigiousAcademies = createCheckBox("EnablePrestigiousAcademies");
+ chkEnableUnitEducation = createCheckBox("EnableUnitEducation");
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("EnableStandardSetsPanel", true,
+ "EnableStandardSetsPanel");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(chkEnableLocalAcademies)
+ .addComponent(chkEnablePrestigiousAcademies)
+ .addComponent(chkEnableUnitEducation)));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(chkEnableLocalAcademies)
+ .addComponent(chkEnablePrestigiousAcademies)
+ .addComponent(chkEnableUnitEducation)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))));
+
+ return panel;
+ }
+
+ /**
+ * Constructs and configures an "XP and Skill Bonuses" {@link JPanel}.
+ * The panel includes a checkbox to enable or disable bonuses, a label
+ * for faculty XP multiplier, and a spinner to adjust the faculty XP multiplier value.
+ *
+ * The layout of the panel is set up with a {@link GroupLayout}, arranging
+ * the checkbox, label, and spinner for optimal vertical and horizontal alignment.
+ *
+ * @return {@link JPanel} The newly created and configured JPanel
+ * containing the XP and Skill Bonuses settings.
+ */
+ private JPanel createXpAndSkillBonusesPanel() {
+ // Contents
+ chkEnableBonuses = createCheckBox("EnableBonuses");
+ lblFacultyXpMultiplier = createLabel("FacultyXpMultiplier");
+ spnFacultyXpMultiplier = createSpinner("FacultyXpMultiplier",
+ 1.00, 0.00, 10.00, 0.01);
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("XpAndSkillBonusesPanel", true,
+ "XpAndSkillBonusesPanel");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(chkEnableBonuses)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblFacultyXpMultiplier)
+ .addComponent(spnFacultyXpMultiplier)));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(chkEnableBonuses)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblFacultyXpMultiplier)
+ .addComponent(spnFacultyXpMultiplier)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))));
+
+ return panel;
+ }
+
+ /**
+ * Constructs and configures a "Dropout Chance" {@link JPanel}.
+ * The created panel includes two labels and spinners: one set for adult dropout chances,
+ * and the other for child dropout chances.
+ *
+ * The JPanel layout is arranged using a {@link GroupLayout}, positioning the labels and spinners
+ * in a way that optimizes horizontal and vertical alignments.
+ *
+ * @return {@link JPanel} The newly constructed and configured JPanel that contains the Dropout Chance settings.
+ */
+ private JPanel createDropoutChancePanel() {
+ // Contents
+ lblAdultDropoutChance = createLabel("AdultDropoutChance");
+ spnAdultDropoutChance = createSpinner("AdultDropoutChance",
+ 1000, 0, 100000, 1);
+ lblChildrenDropoutChance = createLabel("ChildrenDropoutChance");
+ spnChildrenDropoutChance = createSpinner("ChildrenDropoutChance",
+ 10000, 0, 100000, 1);
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("DropoutChancePanel", true,
+ "DropoutChancePanel");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblAdultDropoutChance)
+ .addComponent(spnAdultDropoutChance))
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblChildrenDropoutChance)
+ .addComponent(spnChildrenDropoutChance)));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblAdultDropoutChance)
+ .addComponent(spnAdultDropoutChance)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblChildrenDropoutChance)
+ .addComponent(spnChildrenDropoutChance)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))));
+
+ return panel;
+ }
+
+ /**
+ * Constructs and configures an "Accidents and Events" {@link JPanel}. The panel includes a checkbox
+ * indicating whether to include all ages, a label for military academy accidents, and also a spinner
+ * for adjusting the count of military academy accidents.
+ *
+ * The layout of the panel is configured with a {@link GroupLayout}, organizing the checkbox and
+ * other components for optimized alignments in vertical and horizontal layouts.
+ *
+ * @return {@link JPanel} The constructed, configured JPanel containing "Accidents and Events"
+ * settings
+ */
+ private JPanel createAccidentsAndEventsPanel() {
+ // Contents
+ chkAllAges = createCheckBox("AllAges");
+ lblMilitaryAcademyAccidents = createLabel("MilitaryAcademyAccidents");
+ spnMilitaryAcademyAccidents = createSpinner("MilitaryAcademyAccidents",
+ 10000, 0, 100000, 1);
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("AccidentsAndEventsPanel", true,
+ "AccidentsAndEventsPanel");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(chkAllAges)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblMilitaryAcademyAccidents)
+ .addComponent(spnMilitaryAcademyAccidents)));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(chkAllAges)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblMilitaryAcademyAccidents)
+ .addComponent(spnMilitaryAcademyAccidents)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))));
+
+ return panel;
+ }
+
+ /**
+ * Constructs and configures a "Name and Portrait Generation" {@link JPanel}. This panel contains
+ * various components for managing how names and portraits are generated. It includes a checkbox
+ * for using the origin faction for names, a label and combo box for faction names, a panel for
+ * random portrait selection, and a checkbox for assigning a portrait on role change.
+ *
+ * A {@link GroupLayout} is used to optimally arrange these components for effective vertical
+ * and horizontal alignment.
+ *
+ * @return {@link JPanel} The newly created and configured parent JPanel for the Name and Portrait
+ * Generation tab, containing all relevant name and portrait generation controls.
+ */
+ JPanel createNameAndPortraitGenerationTab() {
+ // Header
+ JPanel headerPanel = createHeaderPanel("NameAndPortraitGenerationTab",
+ getImageDirectory() + "logo_clan_mongoose.png",
+ true);
+
+ // Contents
+ chkUseOriginFactionForNames = createCheckBox("UseOriginFactionForNames");
+
+ lblFactionNames = createLabel("FactionNames");
+
+ pnlRandomPortrait = createRandomPortraitPanel();
+
+ chkAssignPortraitOnRoleChange = createCheckBox("AssignPortraitOnRoleChange");
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("NameAndPortraitGenerationTab", true,
+ "");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(headerPanel)
+ .addComponent(chkUseOriginFactionForNames)
+ .addGroup(layout.createParallelGroup(Alignment.BASELINE)
+ .addComponent(lblFactionNames)
+ .addComponent(comboFactionNames))
+ .addComponent(pnlRandomPortrait)
+ .addComponent(chkAssignPortraitOnRoleChange));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(headerPanel, Alignment.CENTER)
+ .addComponent(chkUseOriginFactionForNames)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lblFactionNames)
+ .addComponent(comboFactionNames)
+ .addContainerGap(Short.MAX_VALUE, Short.MAX_VALUE))
+ .addComponent(pnlRandomPortrait)
+ .addComponent(chkAssignPortraitOnRoleChange)));
+
+ // Create Parent Panel and return
+ return createParentPanel(panel, "NameAndPortraitGenerationTab");
+ }
+
+ /**
+ * Constructs and configures a {@link JPanel} for managing random portrait settings.
+ * The panel contains individual checkboxes for each personnel role defined in {@link PersonnelRole},
+ * as well as two special checkboxes: one for selecting all portraits, and one for selecting none.
+ * Selecting either of these special checkboxes will override the individual role selections and
+ * disable them.
+ *
+ * The panel uses a grid layout, arranging the checkboxes in a grid that extends up to 4 columns,
+ * with each checkbox
+ * representing a particular role. It also has a border around it, titled with the panel's name.
+ *
+ * @return {@link JPanel} The newly constructed and configured JPanel for managing random portrait
+ * settings.
+ */
+ private JPanel createRandomPortraitPanel() {
+ // Contents
+ final PersonnelRole[] personnelRoles = PersonnelRole.values();
+
+ chkUsePortrait = new JCheckBox[personnelRoles.length];
+
+ allPortraitsBox = new JCheckBox(resources.getString("lblAllPortraitsBox.text"));
+ allPortraitsBox.addActionListener(evt -> {
+ final boolean selected = allPortraitsBox.isSelected();
+ for (final JCheckBox box : chkUsePortrait) {
+ if (selected) {
+ box.setSelected(true);
+ }
+ box.setEnabled(!selected);
+ }
+ if (selected) {
+ noPortraitsBox.setSelected(false);
+ }
+ });
+
+ noPortraitsBox = new JCheckBox(resources.getString("lblNoPortraitsBox.text"));
+ noPortraitsBox.addActionListener(evt -> {
+ final boolean selected = noPortraitsBox.isSelected();
+ for (final JCheckBox box : chkUsePortrait) {
+ if (selected) {
+ box.setSelected(false);
+ }
+ box.setEnabled(!selected);
+ }
+ if (selected) {
+ allPortraitsBox.setSelected(false);
+ }
+ });
+
+ // Layout the Panel
+ JPanel panel = new JPanel(
+ new GridLayout((int) Math.ceil((personnelRoles.length + 2) / 4.0), 4));
+ panel.setBorder(BorderFactory.createTitledBorder(
+ String.format(String.format("%s",
+ resources.getString("lblRandomPortraitPanel.text")))));
+
+ panel.add(allPortraitsBox);
+ panel.add(noPortraitsBox);
+
+ // Add remaining checkboxes
+ JCheckBox jCheckBox;
+ for (final PersonnelRole role : PersonnelRole.values()) {
+ jCheckBox = new JCheckBox(role.toString());
+ panel.add(jCheckBox);
+ chkUsePortrait[role.ordinal()] = jCheckBox;
+ }
+
+ return panel;
+ }
+
+ /**
+ * This method is responsible for creating and setting up the RankTab
+ * and its components.
+ *
+ *
The method creates a header panel with a specified logo and then initializes
+ * {@code rankSystemsPane} with a {@code RankSystemsPane} object. The preferred size of the
+ * {@code rankSystemsPane} is set as its minimum and maximum size.
+ *
+ *
The layout is created with a vertical and horizontal group,
+ * to which the components are added sequentially. The {@code headerPanel} and
+ * the view-port component of {@code rankSystemsPane} are added to both layout groups.
+ *
+ *
Finally, the layout components are added to a parent panel which is then returned.
+ *
+ * @return JPanel The parent panel with all the layout components added.
+ */
+ JPanel createRankTab() {
+ // Header
+ JPanel headerPanel = createHeaderPanel("RankTab",
+ getImageDirectory() + "logo_hanseatic_league.png",
+ true);
+
+ // Contents
+ rankSystemsPane = new RankSystemsPane(frame, campaign);
+ Component rankSystemsViewport = rankSystemsPane.getViewport().getView();
+
+ // Layout the Panel
+ final JPanel panel = createStandardPanel("RankTab", true,
+ "");
+ final GroupLayout layout = createStandardLayout(panel);
+ panel.setLayout(layout);
+
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addComponent(headerPanel)
+ .addComponent(rankSystemsViewport));
+
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(Alignment.LEADING)
+ .addComponent(headerPanel, Alignment.CENTER)
+ .addComponent(rankSystemsViewport)));
+
+ // Create Parent Panel and return
+ return createParentPanel(panel, "RankTab");
+ }
+}
diff --git a/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/CampaignOptionsPane.java
new file mode 100644
index 0000000000..b6a818f7c0
--- /dev/null
+++ b/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/CampaignOptionsPane.java
@@ -0,0 +1,252 @@
+package mekhq.gui.panes.campaignOptions.tabs;
+
+import megamek.logging.MMLogger;
+import mekhq.campaign.Campaign;
+import mekhq.gui.baseComponents.AbstractMHQTabbedPane;
+
+import javax.swing.*;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import static java.lang.Math.round;
+import static mekhq.gui.panes.campaignOptions.tabs.CampaignOptionsUtilities.createSubTabs;
+
+public class CampaignOptionsPane extends AbstractMHQTabbedPane {
+ private static final MMLogger logger = MMLogger.create(CampaignOptionsPane.class);
+ private static final String RESOURCE_PACKAGE = "mekhq/resources/NEWCampaignOptionsDialog";
+ private static final ResourceBundle resources = ResourceBundle.getBundle(RESOURCE_PACKAGE);
+
+ private static final int SCROLL_SPEED = 16;
+ private static final int HEADER_FONT_SIZE = 5;
+
+ private final Campaign campaign;
+
+ public CampaignOptionsPane(final JFrame frame, final Campaign campaign) {
+ super(frame, resources, "campaignOptionsDialog");
+ this.campaign = campaign;
+
+ initialize();
+ }
+
+ @Override
+ protected void initialize() {
+ double uiScale = 1;
+ try {
+ uiScale = Double.parseDouble(System.getProperty("flatlaf.uiScale"));
+ } catch (Exception ignored) {}
+
+ addTab(String.format("%s", round(HEADER_FONT_SIZE * uiScale),
+ resources.getString("generalPanel.title")), createGeneralTab());
+
+ createTab("humanResourcesParentTab", createHumanResourcesParentTab());
+ createTab("unitDevelopmentParentTab", createUnitDevelopmentParentTab());
+ createTab("logisticsAndMaintenanceParentTab", createEquipmentAndSuppliesParentTab());
+ createTab("strategicOperationsParentTab", createStrategicOperationsParentTab());
+ }
+
+ /**
+ * Creates a tab and adds it to the TabbedPane.
+ *
+ * @param resourceName the name of the resource used to create the tab's title
+ * @param tab the tab to be added
+ */
+ private void createTab(String resourceName, JTabbedPane tab) {
+ JScrollPane tabScrollPane = new JScrollPane(tab);
+
+ // Increase scroll speed
+ tabScrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_SPEED);
+ tabScrollPane.getHorizontalScrollBar().setUnitIncrement(SCROLL_SPEED);
+
+ // Dynamically adjust font size based on the GUI scale
+ double uiScale = 1;
+ try {
+ uiScale = Double.parseDouble(System.getProperty("flatlaf.uiScale"));
+ } catch (Exception ignored) {}
+
+ addTab(String.format("%s",
+ round(HEADER_FONT_SIZE * uiScale),
+ resources.getString(resourceName + ".title")), tabScrollPane);
+ }
+
+ /**
+ * Creates the General tab.
+ *
+ * @return a {@link JScrollPane} containing the General tab
+ */
+ private JScrollPane createGeneralTab() {
+ GeneralTab generalTab = new GeneralTab(campaign, getFrame(), "generalTab");
+ JPanel createdGeneralTab = generalTab.createGeneralTab();
+
+ return new JScrollPane(createdGeneralTab);
+ }
+
+ /**
+ * The `createHumanResourcesParentTab` method creates and returns a `JTabbedPane` object,
+ * which represents the overarching "Human Resources" tab in the user interface.
+ *
+ * Under the "Human Resources" tab, there are several sub-tabs for different categories, including
+ * Personnel, Biography, Relationships, and Turnover and Retention. Each sub-tab contains various
+ * settings related to its category.
+ *
+ * @return JTabbedPane representing the "Human Resources" tab.
+ */
+ private JTabbedPane createHumanResourcesParentTab() {
+ // Parent Tab
+ JTabbedPane humanResourcesParentTab = new JTabbedPane();
+
+ // Personnel
+ PersonnelTab personnelTab = new PersonnelTab(getFrame(), "personnelTab");
+
+ JTabbedPane personnelContentTabs = createSubTabs(Map.of(
+ "personnelGeneralTab", personnelTab.createGeneralTab(),
+ "personnelLogsTab", personnelTab.createPersonnelLogsTab(),
+ "personnelInformationTab", personnelTab.createPersonnelInformationTab(),
+ "administratorsTab", personnelTab.createAdministratorsTab(),
+ "awardsTab", personnelTab.createAwardsTab(),
+ "prisonersAndDependentsTab", personnelTab.createPrisonersAndDependentsTab(),
+ "medicalTab", personnelTab.createMedicalTab(),
+ "salariesTab", personnelTab.createSalariesTab()));
+
+ // Biography
+ BiographyTab biographyTab = new BiographyTab(campaign, getFrame(), "biographyTab");
+
+ JTabbedPane biographyContentTabs = createSubTabs(Map.of(
+ "biographyGeneralTab", biographyTab.createGeneralTab(),
+ "backgroundsTab", biographyTab.createBackgroundsTab(),
+ "deathTab", biographyTab.createDeathTab(),
+ "educationTab", biographyTab.createEducationTab(),
+ "nameAndPortraitGenerationTab", biographyTab.createNameAndPortraitGenerationTab(),
+ "rankTab", biographyTab.createRankTab()));
+
+ // Relationships
+ RelationshipsTab relationshipsTab = new RelationshipsTab(getFrame(), "relationshipsTab");
+
+ JTabbedPane relationshipsContentTabs = createSubTabs(Map.of(
+ "marriageTab", relationshipsTab.createMarriageTab(),
+ "divorceTab", relationshipsTab.createDivorceTab(),
+ "procreationTab", relationshipsTab.createProcreationTab()));
+
+ // Turnover and Retention
+ TurnoverAndRetentionTab turnoverAndRetentionTab = new TurnoverAndRetentionTab(getFrame(),
+ "turnoverAndRetentionTab");
+
+ JTabbedPane turnoverAndRetentionContentTabs = createSubTabs(Map.of(
+ "turnoverTab", turnoverAndRetentionTab.createTurnoverTab(),
+ "fatigueTab", turnoverAndRetentionTab.createFatigueTab()));
+
+ // Add Tabs
+ humanResourcesParentTab.addTab(String.format("%s", 4,
+ resources.getString("personnelContentTabs.title")), personnelContentTabs);
+ humanResourcesParentTab.addTab(String.format("%s", 4,
+ resources.getString("biographyContentTabs.title")), biographyContentTabs);
+ humanResourcesParentTab.addTab(String.format("%s", 4,
+ resources.getString("relationshipsContentTabs.title")), relationshipsContentTabs);
+ humanResourcesParentTab.addTab(String.format("%s", 4,
+ resources.getString("turnoverAndRetentionContentTabs.title")), turnoverAndRetentionContentTabs);
+
+ addTab(String.format("%s", 4,
+ resources.getString("humanResourcesParentTab.title")), humanResourcesParentTab);
+
+ return humanResourcesParentTab;
+ }
+
+ private JTabbedPane createUnitDevelopmentParentTab() {
+ // Experience
+ // Skills
+ // Skill Randomization
+ // SPAs
+
+ // Parent Tab
+ JTabbedPane unitDevelopmentParentTab = new JTabbedPane();
+
+ return unitDevelopmentParentTab;
+ }
+
+ /**
+ * This `createEquipmentAndSuppliesParentTab` method creates and returns a `JTabbedPane` object.
+ * This represents the "Logistics and Maintenance" parent tab in the user interface.
+ *
+ * @return JTabbedPane representing the "Logistics and Maintenance" tab.
+ */
+ private JTabbedPane createEquipmentAndSuppliesParentTab() {
+ // Parent Tab
+ JTabbedPane equipmentAndSuppliesParentTab = new JTabbedPane();
+
+ // Repair and Maintenance
+ RepairAndMaintenanceTab repairAndMaintenanceTab = new RepairAndMaintenanceTab(getFrame(),
+ "repairAndMaintenanceTab");
+
+ JTabbedPane repairsAndMaintenanceContentTabs = createSubTabs(Map.of(
+ "repairTab", repairAndMaintenanceTab.createRepairTab(),
+ "maintenanceTab", repairAndMaintenanceTab.createMaintenanceTab()));
+
+ // Supplies and Acquisition
+ EquipmentAndSuppliesTab suppliesAndAcquisitionTab = new EquipmentAndSuppliesTab(getFrame(),
+ "suppliesAndAcquisitionTab");
+
+ JTabbedPane suppliesAndAcquisitionContentTabs = createSubTabs(Map.of(
+ "acquisitionTab", suppliesAndAcquisitionTab.createAcquisitionTab(),
+ "deliveryTab", suppliesAndAcquisitionTab.createDeliveryTab(),
+ "planetaryAcquisitionTab", suppliesAndAcquisitionTab.createPlanetaryAcquisitionTab(),
+ "techLimitsTab", suppliesAndAcquisitionTab.createTechLimitsTab()));
+
+ // Add tabs
+ equipmentAndSuppliesParentTab.addTab(String.format("%s", 4,
+ resources.getString("suppliesAndAcquisitionContentTabs.title")), suppliesAndAcquisitionContentTabs);
+ equipmentAndSuppliesParentTab.addTab(String.format("%s", 4,
+ resources.getString("repairsAndMaintenanceContentTabs.title")), repairsAndMaintenanceContentTabs);
+
+ addTab(String.format("%s", 4,
+ resources.getString("logisticsAndMaintenanceParentTab.title")), equipmentAndSuppliesParentTab);
+
+ return equipmentAndSuppliesParentTab;
+ }
+
+ private JTabbedPane createStrategicOperationsParentTab() {
+ // Parent Tab
+ JTabbedPane strategicOperationsParentTab = new JTabbedPane();
+
+ // Finances
+ FinancesTab financesTab = new FinancesTab(campaign, getFrame(), "financesTab");
+
+ JTabbedPane financesContentTabs = createSubTabs(Map.of(
+ "financesGeneralTab", financesTab.createFinancesGeneralOptionsTab(),
+ "priceMultipliersTab", financesTab.createPriceMultipliersTab()));
+
+ // Markets
+ MarketsTab marketsTab = new MarketsTab(getFrame(), "marketsTab");
+
+ JTabbedPane marketsContentTabs = createSubTabs(Map.of(
+ "personnelMarketTab", marketsTab.createPersonnelMarketTab(),
+ "unitMarketTab", marketsTab.createUnitMarketTab(),
+ "contractMarketTab", marketsTab.createContractMarketTab()));
+
+ // Rulesets
+ RulesetsTab rulesetsTab = new RulesetsTab(getFrame(), "rulesetsTab");
+
+ JTabbedPane rulesetsContentTabs = createSubTabs(Map.of(
+ "stratConGeneralTab", rulesetsTab.createStratConTab(),
+ "legacyTab", rulesetsTab.createLegacyTab()));
+
+ // Add tabs
+ strategicOperationsParentTab.addTab(String.format("%s", 4,
+ resources.getString("financesContentTabs.title")), financesContentTabs);
+ strategicOperationsParentTab.addTab(String.format("%s", 4,
+ resources.getString("marketsContentTabs.title")), marketsContentTabs);
+ strategicOperationsParentTab.addTab(String.format("%s", 4,
+ resources.getString("rulesetsContentTabs.title")), rulesetsContentTabs);
+
+ addTab(String.format("%s", 4,
+ resources.getString("strategicOperationsParentTab.title")), strategicOperationsParentTab);
+
+ return strategicOperationsParentTab;
+ }
+
+ private void setOptions() {
+ // TODO this is where we update the dialog based on current campaign settings.
+ }
+
+ private void updateOptions() {
+ // TODO this is where we update campaign values based on the dialog values
+ }
+}
diff --git a/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/CampaignOptionsUtilities.java b/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/CampaignOptionsUtilities.java
new file mode 100644
index 0000000000..201c8f5d46
--- /dev/null
+++ b/MekHQ/src/mekhq/gui/panes/campaignOptions/tabs/CampaignOptionsUtilities.java
@@ -0,0 +1,504 @@
+package mekhq.gui.panes.campaignOptions.tabs;
+
+import megamek.client.ui.swing.util.FlatLafStyleBuilder;
+import megamek.client.ui.swing.util.UIUtil;
+import megamek.common.annotations.Nullable;
+import mekhq.MHQConstants;
+
+import javax.swing.*;
+import javax.swing.GroupLayout.Alignment;
+import javax.swing.JSpinner.DefaultEditor;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import static megamek.client.ui.WrapLayout.wordWrap;
+
+public class CampaignOptionsUtilities {
+ private static final String RESOURCE_PACKAGE = "mekhq/resources/NEWCampaignOptionsDialog";
+ static final ResourceBundle resources = ResourceBundle.getBundle(RESOURCE_PACKAGE);
+ final static String IMAGE_DIRECTORY = "data/images/universe/factions/";
+
+ /**
+ * @return the image directory
+ */
+ static String getImageDirectory() {
+ return IMAGE_DIRECTORY;
+ }
+
+ static JCheckBox createCheckBox(String name) {
+ return createCheckBox(name, null);
+ }
+
+ /**
+ * Returns a new {@link JCheckBox} object.
+ *
+ * The {@link JCheckBox} will be named {@code "chk" + name}, and use the following resource bundle references:
+ * {@code "lbl" + name + ".text"} and {@code "lbl" + name + ".tooltip"}.
+ *
+ * @param name the name of the checkbox
+ * @param customWrapSize the maximum number of characters (including whitespaces) on each
+ * line of the tooltip (or 100, if {@code null}).
+ * @return a new {@link JCheckBox} object with the specified name, label, and tooltip
+ */
+ static JCheckBox createCheckBox(String name, @Nullable Integer customWrapSize) {
+ customWrapSize = processWrapSize(customWrapSize);
+
+ JCheckBox checkBox = new JCheckBox(String.format("%s",
+ resources.getString("lbl" + name + ".text")));
+ checkBox.setToolTipText(wordWrap(resources.getString("lbl" + name + ".tooltip"), customWrapSize));
+ checkBox.setName("chk" + name);
+
+// Dimension size = checkBox.getPreferredSize();
+// checkBox.setMinimumSize(UIUtil.scaleForGUI(size.width, size.height));
+
+ return checkBox;
+ }
+
+ /**
+ * Creates a {@link JSpinner} object.
+ *
+ * The name of the {@link JSpinner} will be {@code "spn" + name},
+ * and it will use the {@code "lbl" + name + ".tooltip"} resource bundle item
+ *
+ * @param name a string representing the name of the objects.
+ * @param defaultValue The default value of the spinner
+ * @param minimum The minimum value of the spinner
+ * @param maximum The maximum value of the spinner
+ * @param stepSize The step size of the spinner
+ * @return The created {@link JSpinner}.
+ */
+ static JSpinner createSpinner(String name, double defaultValue, double minimum, double maximum,
+ double stepSize) {
+ return createSpinner(name, null, defaultValue, minimum, maximum, stepSize);
+ }
+
+ /**
+ * Creates a {@link JSpinner} object.
+ *
+ * The name of the {@link JSpinner} will be {@code "spn" + name},
+ * and it will use the {@code "lbl" + name + ".tooltip"} resource bundle item
+ *
+ * @param name a string representing the name of the objects.
+ * @param customWrapSize the maximum number of characters (including whitespaces) on each
+ * line of the tooltip (or 100, if {@code null}).
+ * @param defaultValue The default value of the spinner
+ * @param minimum The minimum value of the spinner
+ * @param maximum The maximum value of the spinner
+ * @param stepSize The step size of the spinner
+ * @return The created {@link JSpinner}.
+ */
+ static JSpinner createSpinner(String name, @Nullable Integer customWrapSize, double defaultValue,
+ double minimum, double maximum, double stepSize) {
+ customWrapSize = processWrapSize(customWrapSize);
+
+ JSpinner jSpinner = new JSpinner();
+ jSpinner.setModel(new SpinnerNumberModel(defaultValue, minimum, maximum, stepSize));
+ jSpinner.setToolTipText(wordWrap(resources.getString("lbl" + name + ".tooltip"), customWrapSize));
+ jSpinner.setName("spn" + name);
+
+ DefaultEditor editor = (DefaultEditor) jSpinner.getEditor();
+ editor.getTextField().setHorizontalAlignment(JTextField.LEFT);
+
+// Dimension size = jSpinner.getPreferredSize();
+// jSpinner.setMinimumSize(UIUtil.scaleForGUI(size.width, size.height));
+
+ return jSpinner;
+ }
+
+ /**
+ * Creates a {@link JLabel} with the specified name and optional customWrapSize.
+ *
+ * Please note that 'name' is also used to fetch the resources associated with this label.
+ * For the label text 'name' is appended by '.text'.
+ * For the label tooltip 'name' is appended with '.tooltip'.
+ * These values must exist in the resource bundle otherwise an error will be thrown.
+ *
+ * @param name the name of the label
+ * @return a new {@link JLabel} object
+ */
+ static JLabel createLabel(String name) {
+ return createLabel(name, null);
+ }
+
+ /**
+ * Creates a {@link JLabel} with the specified name and optional customWrapSize.
+ *
+ * Please note that 'name' is also used to fetch the resources associated with this label.
+ * For the label text 'name' is appended by '.text'.
+ * For the label tooltip 'name' is appended with '.tooltip'.
+ * These values must exist in the resource bundle otherwise an error will be thrown.
+ *
+ * @param name the name of the label
+ * @param customWrapSize the maximum number of characters (including whitespaces) on each line
+ * of the tooltip; defaults to 100 if {@code null}
+ * @return a new {@link JLabel} object
+ */
+ static JLabel createLabel(String name, @Nullable Integer customWrapSize) {
+ customWrapSize = processWrapSize(customWrapSize);
+
+ JLabel jLabel = new JLabel(String.format("%s",
+ resources.getString("lbl" + name + ".text")));
+ jLabel.setToolTipText(wordWrap(resources.getString("lbl" + name + ".tooltip"), customWrapSize));
+ jLabel.setName("lbl" + name);
+
+// Dimension size = jLabel.getPreferredSize();
+// jLabel.setMinimumSize(UIUtil.scaleForGUI(size.width, size.height));
+
+ return jLabel;
+ }
+
+ static class COptionLabel extends JLabel {
+
+ public COptionLabel(String name) {
+ this(name, null);
+ }
+
+ public COptionLabel(String name, @Nullable Integer customWrapSize) {
+ super(String.format("%s",
+ resources.getString("lbl" + name + ".text")));
+ setToolTipText(wordWrap(resources.getString("lbl" + name + ".tooltip"), processWrapSize(customWrapSize)));
+ setName("lbl" + name);
+ }
+ }
+
+ /**
+ * Creates a {@link JTextField} object.
+ *
+ * The name of the {@link JTextField} will be {@code}, and it will use the following resource bundle reference:
+ * {@code "lbl" + name + ".tooltip"}.
+ *
+ * @param name the name of the object.
+ * @param width The width of the {@link JTextField}.
+ * @return a map containing a {@link JLabel} key and a {@link JTextField} value.
+ */
+ static JTextField createTextField(String name, int width) {
+ return createTextField(name, null, width);
+ }
+
+ /**
+ * Creates a {@link JTextField} object.
+ *
+ * The name of the {@link JTextField} will be {@code}, and it will use the following resource bundle reference:
+ * {@code "lbl" + name + ".tooltip"}.
+ *
+ * @param name the name of the object.
+ * @param customWrapSize the maximum number of characters (including whitespaces) on each
+ * line of the tooltip.
+ * If {@code null}, the default wrap size of 100 is used.
+ * @param width The width of the {@link JTextField}.
+ * @return a map containing a {@link JLabel} key and a {@link JTextField} value.
+ */
+ static JTextField createTextField(String name, @Nullable Integer customWrapSize, int width) {
+ customWrapSize = processWrapSize(customWrapSize);
+
+ JTextField jTextField = new JTextField();
+ jTextField.setToolTipText(wordWrap(resources.getString("lbl" + name + ".tooltip"), customWrapSize));
+ jTextField.setName("txt" + name);
+
+// int preferredHeight = jTextField.getPreferredSize().height;
+// jTextField.setMinimumSize(UIUtil.scaleForGUI(width, preferredHeight));
+// jTextField.setMaximumSize(UIUtil.scaleForGUI(width, preferredHeight));
+
+ return jTextField;
+ }
+
+ /**
+ * Returns the maximum number of characters on each line of a tooltip.
+ * If a custom wrap size is provided, it is returned.
+ * Otherwise, the default wrap size of 100 is returned.
+ *
+ * @param customWrapSize the maximum number of characters (including whitespaces) on each line
+ * of the tooltip, or {@code null} if no custom wrap size is specified
+ * @return the maximum number of characters on each line of a tooltip
+ */
+ private static int processWrapSize(@Nullable Integer customWrapSize) {
+ return customWrapSize == null ? 100 : customWrapSize;
+ }
+
+ /**
+ * Creates a standard {@link JPanel} with a titled border.
+ *
+ * {@code createStandardLayout} should also be called and the resulting {@link GroupLayout}
+ * assigned to the panel via {@code setLayout}.
+ *
+ * If {@code borderTitle} isn't empty the resource bundle reference, used to fetch the border's
+ * title, will be {@code "lbl" + borderTitle + ".text"}
+ *
+ * @param name the name of the panel.
+ * @param includeBorder whether the panel should have a border.
+ *
+ * @return a {@link JPanel} with a titled border and {@link GroupLayout} as its layout manager
+ */
+ static JPanel createStandardPanel(String name, boolean includeBorder) {
+ return createStandardPanel(name, includeBorder, "");
+ }
+
+ /**
+ * Creates a standard {@link JPanel} with a titled border.
+ *
+ * {@code createStandardLayout} should also be called and the resulting {@link GroupLayout}
+ * assigned to the panel via {@code setLayout}.
+ *
+ * If {@code borderTitle} isn't empty the resource bundle reference, used to fetch the border's
+ * title, will be {@code "lbl" + borderTitle + ".text"}
+ *
+ * @param name the name of the panel.
+ * @param includeBorder whether the panel should have a border.
+ * @param borderTitle The resource string that should be used as the title of the border.
+ * Can be empty to generate an untitled border.
+ *
+ * @return a {@link JPanel} with a titled border and {@link GroupLayout} as its layout manager
+ */
+ static JPanel createStandardPanel(String name, boolean includeBorder, String borderTitle) {
+ borderTitle = borderTitle.isBlank() ? "" : resources.getString("lbl" + borderTitle + ".text");
+
+ JPanel panel = new JPanel() {
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension standardSize = super.getPreferredSize();
+ return new Dimension(Math.max(standardSize.width, UIUtil.scaleForGUI(500)), standardSize.height);
+ }
+ };
+
+ if (includeBorder) {
+ panel.setBorder(BorderFactory.createTitledBorder(
+ String.format(String.format("%s", borderTitle))));
+ }
+
+ panel.setName(name);
+
+// Dimension size = panel.getPreferredSize();
+// int sizeHeight = size.height;
+// int sizeWidth = size.width;
+// for (Component component : panel.getComponents()) {
+// sizeHeight += component.getPreferredSize().height;
+// sizeWidth += component.getPreferredSize().width;
+// }
+//
+// if (sizeWidth < 750) {
+// sizeWidth = 750;
+// }
+//
+// panel.setMaximumSize(UIUtil.scaleForGUI(sizeWidth, sizeHeight));
+
+ return panel;
+ }
+
+ /**
+ * Creates a {@link JPanel} consisting of a {@link JLabel} above an image.
+ * If {@code includeBodyText} is {@code true} a second {@link JLabel} is placed after the first.
+ *
+ * The {@link JPanel} will be named {@code "pnl" + name + "HeaderPanel"}.
+ * The resource bundle references for the first {@link JLabel} will be {@code "lbl" + name + ".text"}.
+ * The optional second {@link JLabel} is assigned the name {@code ""lbl" + name + "Body"}
+ * and uses the following resource bundle reference: {@code "lbl" + name + "Body.text"}.
+ *
+ * @param name the name of the header panel.
+ * @param imageAddress the file path of the image to be displayed in the panel
+ * @param includeBodyText if {@code true}, include a second {@link JLabel}.
+ * @return a {@link JPanel} representing the header panel
+ */
+ static JPanel createHeaderPanel(String name, String imageAddress, boolean includeBodyText) {
+ ImageIcon imageIcon = new ImageIcon(imageAddress);
+ JLabel imageLabel = new JLabel(imageIcon);
+
+ final JLabel lblHeader = new JLabel(resources.getString("lbl" + name + ".text"), SwingConstants.CENTER);
+ new FlatLafStyleBuilder().bold().size(3).apply(lblHeader);
+ lblHeader.setName("lbl" + name);
+
+ JLabel lblBody = new JLabel();
+ if (includeBodyText) {
+ lblBody = new JLabel(String.format("
%s
",
+ resources.getString("lbl" + name + "Body.text")), SwingConstants.CENTER);
+ lblBody.setName("lbl" + name + "Body");
+// Dimension size = lblBody.getPreferredSize();
+// lblBody.setMaximumSize(UIUtil.scaleForGUI(750, size.height));
+ }
+
+ final JPanel panel = createStandardPanel("pnl" + name + "HeaderPanel", false, "");
+// Dimension size = panel.getPreferredSize();
+// panel.setPreferredSize(UIUtil.scaleForGUI(750, size.height));
+
+ panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+
+ panel.add(lblHeader);
+ panel.add(lblBody);
+ panel.add(imageLabel);
+
+
+// final GroupLayout layout = createStandardLayout(panel);
+// panel.setLayout(layout);
+//
+// layout.setVerticalGroup(
+// layout.createSequentialGroup()
+// .addComponent(lblHeader)
+// .addComponent(lblBody)
+// .addComponent(imageLabel));
+//
+// layout.setHorizontalGroup(
+// layout.createParallelGroup(Alignment.CENTER)
+// .addComponent(lblHeader)
+// .addComponent(lblBody)
+// .addComponent(imageLabel));
+
+ return panel;
+ }
+
+ /**
+ * Creates a {@link GroupLayout} object for the specified {@link JPanel}.
+ *
+ * Written to be paired with {@code createStandardPanel}.
+ *
+ * @param panel the {@link JPanel} for which the {@link GroupLayout} is created
+ * @return the created {@link GroupLayout} object
+ */
+ static GroupLayout createStandardLayout(JPanel panel) {
+ final GroupLayout layout = new GroupLayout(panel);
+ layout.setAutoCreateGaps(true);
+ layout.setAutoCreateContainerGaps(true);
+
+ return layout;
+ }
+
+ /**
+ * Creates a parent panel for the provided {@link JPanel}.
+ *
+ * @param panel the panel to be added to the parent panel
+ * @param name the name of the parent panel
+ * @return the created {@link JPanel}
+ */
+ static JPanel createParentPanel(JPanel panel, String name) {
+ // Create Panel
+ final JPanel parentPanel = createStandardPanel(name, false, "");
+ final GroupLayout parentLayout = createStandardLayout(parentPanel);
+
+ // Set Dimensions
+ int widthNew = parentPanel.getMinimumSize().width;
+
+ if (widthNew < UIUtil.scaleForGUI(750)) {
+ widthNew = UIUtil.scaleForGUI(750);
+ }
+
+ int height = parentPanel.getPreferredSize().height;
+ for (Component component : panel.getComponents()) {
+ if (component instanceof JPanel) {
+ height += component.getPreferredSize().height;
+ }
+ }
+
+// Dimension size = new Dimension(widthNew, height);
+// parentPanel.setMinimumSize(UIUtil.scaleForGUI(size.width, size.height));
+// parentPanel.setMaximumSize(UIUtil.scaleForGUI(size.width, size.height));
+
+ // Layout
+ parentPanel.setLayout(parentLayout);
+
+ parentLayout.setVerticalGroup(
+ parentLayout.createSequentialGroup()
+ .addComponent(panel));
+
+ parentLayout.setHorizontalGroup(
+ parentLayout.createParallelGroup(Alignment.CENTER)
+ .addComponent(panel));
+
+ return parentPanel;
+ }
+
+ /**
+ * Creates a new instance of {@link JTabbedPane} with the supplied panels as tabs.
+ *
+ * The resource bundle reference for the individual tabs will be {@code panel.getName() + ".title"}
+ *
+ * @param panels a map containing the names of the panels as keys and the corresponding
+ * {@link JPanel} objects as values
+ * @return a {@link JTabbedPane} with the supplied panels as tabs
+ */
+ static JTabbedPane createSubTabs(Map panels) {
+ // We use a list here to ensure that the tabs always display in the same order,
+ // and that order might as well be alphabetic.
+ List tabNames = new ArrayList<>(panels.keySet());
+ tabNames.sort(String.CASE_INSENSITIVE_ORDER);
+
+ // This is a special case handler to ensure 'general options' tabs always appear first
+ int indexToMoveToFront = -1;
+ for (int i=0; i%s