Skip to content

Commit

Permalink
Merge branch 'master' into campaignOptions_fixedMapStepSize
Browse files Browse the repository at this point in the history
IllianiCBT authored Jun 21, 2024
2 parents cc7c6c7 + 00ed497 commit 24d745c
Showing 25 changed files with 342 additions and 81 deletions.
4 changes: 4 additions & 0 deletions MekHQ/data/universe/factions.xml
Original file line number Diff line number Diff line change
@@ -1101,6 +1101,8 @@ successor - unimplemented tag describing another faction code as the specified f
<faction>
<shortname>FC</shortname>
<fullname>Federated Commonwealth</fullname>
<altNamesByYear year='3028'>Federated Commonwealth Alliance</altNamesByYear>
<altNamesByYear year='3055'>Federated Commonwealth</altNamesByYear>
<alternativeFactionCodes>FS,LA</alternativeFactionCodes>
<startingPlanet>New Avalon</startingPlanet>
<eraMods>0,0,0,1,2,2,1,0,0</eraMods>
@@ -1110,6 +1112,8 @@ successor - unimplemented tag describing another faction code as the specified f
<layeredForceIconLogoFilename>Federated Commonwealth.png</layeredForceIconLogoFilename>
<colorRGB>248,212,44</colorRGB>
<tags>is,super,playable</tags>
<start>3028</start>
<end>3068</end>
</faction>
<faction>
<shortname>FVC</shortname>
4 changes: 4 additions & 0 deletions MekHQ/data/universe/planetary_systems/system_events.xml
Original file line number Diff line number Diff line change
@@ -932465,6 +932465,10 @@
<date>3064-01-05</date>
<faction source="canon">FC</faction>
</event>
<event>
<date>3063-01-01</date>
<faction source="noncanon">LA</faction>
</event>
<event>
<date>3070-01-01</date>
<population source="noncanon">5162011707</population>
Binary file modified MekHQ/docs/Personnel Modules/Awards Module.pdf
Binary file not shown.
Binary file modified MekHQ/docs/Personnel Modules/Turnover & Retention Module.pdf
Binary file not shown.
3 changes: 3 additions & 0 deletions MekHQ/resources/mekhq/resources/Education.properties
Original file line number Diff line number Diff line change
@@ -28,6 +28,9 @@ typeInstitute.text=Institute
typeUniversity.text=University
typePolytechnic.text=Polytechnic
typeSchool.text=School
typeSchoolBoarding.text=Boarding School
typeFinishingSchool.text=Finishing School
typePreparatorySchool.text=Preparatory School

#### Academy Suffix
suffixTechnology.text=Technology
11 changes: 9 additions & 2 deletions MekHQ/resources/mekhq/resources/GUI.properties
Original file line number Diff line number Diff line change
@@ -336,6 +336,10 @@ UnresolvedStratConContactsNagDialog.text=You have unresolved contacts on the Str
cargoCapacityNagDialog.title=Exceeded Cargo Capacity
cargoCapacityNagDialog.text=You have exceeded your available cargo capacity. Do you really wish to advance the day?

### FactionDestroyedNagDialog Class
InvalidFactionNagDialog.title=Invalid Faction
InvalidFactionNagDialog.text=Your campaign faction is invalid. Either it has not yet been created, or it has been destroyed.\n\nPlease pick a new faction in campaign options.\nAdvance day anyway?

#### Report Dialogs
### CargoReportDialog Class
CargoReportDialog.title=Cargo Report
@@ -713,6 +717,8 @@ optionOutstandingScenariosNag.text=Hide Outstanding Scenarios Nag
optionOutstandingScenariosNag.toolTipText=This allows you to ignore the daily warning for having unfinished scenarios on the current day.
optionCargoCapacityNag.text=Hide Exceeded Cargo Capacity Nag
optionCargoCapacityNag.toolTipText=This allows you to ignore the daily warning for having exceeded your available cargo capacity.
optionInvalidFactionNag.text=Hide Invalid Faction Nag
optionInvalidFactionNag.toolTipText=This allows you to ignore the daily warning for having an invalid faction.
## Miscellaneous Tab
miscellaneousTab.title=Miscellaneous Options
lblUserDir.text=User Files Directory:
@@ -1287,8 +1293,9 @@ chkFilterByPercentageOfCost.text=Show only units at
chkFilterByPercentageOfCost.toolTipText=Filter out units above the specified percentage of market value.
spnFilterByPercentageOfCost.toolTipText=Filter out units with market value above this percentage when the filter is enabled.
lblCostPercentageThreshold.text=% of market value or lower
### Black Market Panel
lblBlackMarketWarning.text=<html><b>Open Market & Mercenary Auction:</b> The public sale of units available to your campaign faction\
### Market Description Panel
lblMarketDescriptions.text=<html><b>Open Market:</b> The public sale of units available to your campaign faction\
<br><b>Mercenary Auction:</b> The sale of unwanted units sold through the MRBC (or the era-appropriate equivalent)\
<br><b>Employer Market:</b> Units or salvage no longer wanted by your employer\
<br><b>Factory Line:</b> Brand-new units fresh off the production line\
<br><b>Black Market:</b> Potentially brand-new units which come with the risk of being swindled</html>
1 change: 1 addition & 0 deletions MekHQ/src/mekhq/MHQConstants.java
Original file line number Diff line number Diff line change
@@ -176,6 +176,7 @@ public final class MHQConstants extends SuiteConstants {
public static final String NAG_UNRESOLVED_STRATCON_CONTACTS = "nagUnresolvedStratConContacts";
public static final String NAG_OUTSTANDING_SCENARIOS = "nagOutstandingScenarios";
public static final String NAG_CARGO_CAPACITY = "nagCargoCapacity";
public static final String NAG_INVALID_FACTION = "nagInvalidFaction";
//endregion Nag Tab

//region Miscellaneous Options
6 changes: 6 additions & 0 deletions MekHQ/src/mekhq/campaign/Campaign.java
Original file line number Diff line number Diff line change
@@ -1334,6 +1334,12 @@ public Person newDependent(boolean baby) {
Gender.RANDOMIZE);
}

if (person.getAge(getLocalDate()) <= 16) {
person.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD);
} else {
person.setEduHighestEducation(EducationLevel.HIGH_SCHOOL);
}

return person;
}

1 change: 1 addition & 0 deletions MekHQ/src/mekhq/campaign/ResolveScenarioTracker.java
Original file line number Diff line number Diff line change
@@ -1475,6 +1475,7 @@ public void resolveScenario(ScenarioStatus resolution, String report) {
person.getHyperlinkedName()));
}

// prisoners should generate with lower than average loyalty, so only roll 2d6
person.generateLoyalty(Compute.d6(2));
} else {
continue;
42 changes: 42 additions & 0 deletions MekHQ/src/mekhq/campaign/market/enums/UnitMarketType.java
Original file line number Diff line number Diff line change
@@ -108,7 +108,49 @@ public String toString() {
return name;
}

/**
* Calculates the price percentage based on a given modifier and d6 roll.
*
* @param modifier the modifier to adjust the price (a negative modifier decreases price, positive increases price)
* @return the calculated price
* @throws IllegalStateException if the roll value is unexpected
*/
public static int getPricePercentage(int modifier) {
int roll = Compute.d6(2);
int value;

switch (roll) {
case 2:
value = modifier + 3;
break;
case 3:
value = modifier + 2;
break;
case 4:
case 5:
value = modifier + 1;
break;
case 6:
case 7:
case 8:
value = modifier;
break;
case 9:
case 10:
value = modifier - 1;
break;
case 11:
value = modifier - 2;
break;
case 12:
value = modifier - 3;
break;
default:
throw new IllegalStateException("Unexpected value in mekhq/campaign/market/unitMarket/AtBMonthlyUnitMarket.java/getPrice: " + roll);
}

return 100 + (value * 5);
}

/**
* Returns the quality of a unit based on the given market type.
Original file line number Diff line number Diff line change
@@ -39,6 +39,8 @@
import java.util.Collection;
import java.util.List;

import static mekhq.campaign.market.enums.UnitMarketType.getPricePercentage;

public class AtBMonthlyUnitMarket extends AbstractUnitMarket {
//region Constructors
public AtBMonthlyUnitMarket() {
@@ -76,70 +78,70 @@ public void generateUnitOffers(final Campaign campaign) {
Faction faction = campaign.getFaction();

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.OPEN, UnitType.MEK,
faction, IUnitRating.DRAGOON_F, 6);
faction, IUnitRating.DRAGOON_F, 1);

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.OPEN, UnitType.AEROSPACEFIGHTER,
faction, IUnitRating.DRAGOON_F, 6);
faction, IUnitRating.DRAGOON_F, 1);

addOffers(campaign, getMarketItemCount("very common"), UnitMarketType.OPEN, UnitType.TANK,
faction, IUnitRating.DRAGOON_F, 6);
faction, IUnitRating.DRAGOON_F, 1);

addOffers(campaign, getMarketItemCount("common"), UnitMarketType.OPEN, UnitType.CONV_FIGHTER,
faction, IUnitRating.DRAGOON_F, 6);
faction, IUnitRating.DRAGOON_F, 1);

if ((contract != null) && (campaign.getLocalDate().isAfter(contract.getStartDate().minusDays(1)))) {
// Employer Market
faction = contract.getEmployerFaction();

addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.EMPLOYER, UnitType.MEK,
faction, IUnitRating.DRAGOON_D, 8);
faction, IUnitRating.DRAGOON_D, -1);

addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.EMPLOYER, UnitType.AEROSPACEFIGHTER,
faction, IUnitRating.DRAGOON_D, 8);
faction, IUnitRating.DRAGOON_D, -1);

addOffers(campaign, getMarketItemCount("common"), UnitMarketType.EMPLOYER, UnitType.TANK,
faction, IUnitRating.DRAGOON_D, 8);
faction, IUnitRating.DRAGOON_D, -1);

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.EMPLOYER, UnitType.CONV_FIGHTER,
faction, IUnitRating.DRAGOON_D, 8);
faction, IUnitRating.DRAGOON_D, -1);

// Unwanted Salvage Market
faction = contract.getEnemy();

addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.EMPLOYER, UnitType.MEK,
faction, IUnitRating.DRAGOON_F, 5);
faction, IUnitRating.DRAGOON_F, 2);

addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.EMPLOYER, UnitType.AEROSPACEFIGHTER,
faction, IUnitRating.DRAGOON_F, 5);
faction, IUnitRating.DRAGOON_F, 2);

addOffers(campaign, getMarketItemCount("common"), UnitMarketType.EMPLOYER, UnitType.TANK,
faction, IUnitRating.DRAGOON_F, 5);
faction, IUnitRating.DRAGOON_F, 2);

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.EMPLOYER, UnitType.CONV_FIGHTER,
faction, IUnitRating.DRAGOON_F, 5);
faction, IUnitRating.DRAGOON_F, 2);
}

// Mercenary Market
if (!campaign.getFaction().isClan()) {
faction = Factions.getInstance().getFaction("MERC");

int modifier = -1;
int modifier = 1;

if (campaign.getFaction().isMercenary()) {
modifier = 1;
modifier = -1;
}

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.MERCENARY, UnitType.MEK,
faction, IUnitRating.DRAGOON_C, 7 + modifier);
faction, IUnitRating.DRAGOON_C, modifier);

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.MERCENARY, UnitType.AEROSPACEFIGHTER,
faction, IUnitRating.DRAGOON_C, 7 + modifier);
faction, IUnitRating.DRAGOON_C, modifier);

addOffers(campaign, getMarketItemCount("very common"), UnitMarketType.MERCENARY, UnitType.TANK,
faction, IUnitRating.DRAGOON_C, 7 + modifier);
faction, IUnitRating.DRAGOON_C, modifier);

addOffers(campaign, getMarketItemCount("common"), UnitMarketType.MERCENARY, UnitType.CONV_FIGHTER,
faction, IUnitRating.DRAGOON_C, 7 + modifier);
faction, IUnitRating.DRAGOON_C, modifier);
}

// Factory Market
@@ -149,16 +151,16 @@ public void generateUnitOffers(final Campaign campaign) {

if ((!campaign.getFaction().isClan()) && (faction != null) && (!faction.isClan())) {
addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.FACTORY, UnitType.MEK,
faction, IUnitRating.DRAGOON_A, 6);
faction, IUnitRating.DRAGOON_A, 2);

addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.FACTORY, UnitType.AEROSPACEFIGHTER,
faction, IUnitRating.DRAGOON_A, 6);
faction, IUnitRating.DRAGOON_A, 2);

addOffers(campaign, getMarketItemCount("common"), UnitMarketType.FACTORY, UnitType.TANK,
faction, IUnitRating.DRAGOON_A, 6);
faction, IUnitRating.DRAGOON_A, 2);

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.FACTORY, UnitType.CONV_FIGHTER,
faction, IUnitRating.DRAGOON_A, 6);
faction, IUnitRating.DRAGOON_A, 2);
}
}

@@ -167,13 +169,13 @@ public void generateUnitOffers(final Campaign campaign) {
// Clan Factory Market
if ((faction.isClan()) && (campaign.getCurrentSystem().getFactionSet(campaign.getLocalDate()).contains(faction))) {
addOffers(campaign, getMarketItemCount("very common"), UnitMarketType.FACTORY, UnitType.MEK,
faction, IUnitRating.DRAGOON_A, 9);
faction, IUnitRating.DRAGOON_A, -4);

addOffers(campaign, getMarketItemCount("common"), UnitMarketType.FACTORY, UnitType.AEROSPACEFIGHTER,
faction, IUnitRating.DRAGOON_A, 9);
faction, IUnitRating.DRAGOON_A, -4);

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.FACTORY, UnitType.TANK,
faction, IUnitRating.DRAGOON_A, 9);
faction, IUnitRating.DRAGOON_A, -4);
}

// Black Market
@@ -182,16 +184,16 @@ public void generateUnitOffers(final Campaign campaign) {
.getFactionSet(campaign.getLocalDate()));

addOffers(campaign, getMarketItemCount("very rare"), UnitMarketType.BLACK_MARKET, UnitType.MEK,
faction, IUnitRating.DRAGOON_A, 9);
faction, IUnitRating.DRAGOON_A, -8);

addOffers(campaign, getMarketItemCount("very rare"), UnitMarketType.BLACK_MARKET, UnitType.AEROSPACEFIGHTER,
faction, IUnitRating.DRAGOON_A, 9);
faction, IUnitRating.DRAGOON_A, -8);

addOffers(campaign, getMarketItemCount("uncommon"), UnitMarketType.BLACK_MARKET, UnitType.TANK,
faction, IUnitRating.DRAGOON_A, 9);
addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.BLACK_MARKET, UnitType.TANK,
faction, IUnitRating.DRAGOON_A, -8);

addOffers(campaign, getMarketItemCount("rare"), UnitMarketType.BLACK_MARKET, UnitType.CONV_FIGHTER,
faction, IUnitRating.DRAGOON_A, 9);
faction, IUnitRating.DRAGOON_A, -8);
}

writeRefreshReport(campaign);
@@ -224,7 +226,7 @@ private int getMarketItemCount(String rarity) {
@Override
public void addOffers(final Campaign campaign, final int num, UnitMarketType market,
final int unitType, @Nullable Faction faction, final int quality,
final int priceTarget) {
final int priceModifier) {
if (faction == null) {
faction = RandomFactionGenerator.getInstance().getEmployerFaction();
}
@@ -268,8 +270,7 @@ public void addOffers(final Campaign campaign, final int num, UnitMarketType mar
}
}

final int percent = 100 - (Compute.d6(2) - priceTarget) * 5;
addSingleUnit(campaign, market, unitType, faction, quality, movementModes, missionRoles, percent);
addSingleUnit(campaign, market, unitType, faction, quality, movementModes, missionRoles, getPricePercentage(priceModifier));
}
}

4 changes: 2 additions & 2 deletions MekHQ/src/mekhq/campaign/personnel/Person.java
Original file line number Diff line number Diff line change
@@ -3800,7 +3800,7 @@ public void fixReferences(final Campaign campaign) {
* @throws IllegalArgumentException if the provided roll is not between 3 and 18
*/
public void generateLoyalty(int roll) {
if (roll == 3) {
if (roll <= 3) {
setLoyalty(3);
} else if (roll == 4) {
setLoyalty(2);
@@ -3812,7 +3812,7 @@ public void generateLoyalty(int roll) {
setLoyalty(-1);
} else if (roll == 17) {
setLoyalty(-2);
} else if (roll == 18){
} else if (roll >= 18){
setLoyalty(-3);
} else {
throw new IllegalArgumentException("Invalid roll in mekhq/campaign/personnel/Person.java/generateLoyalty: " + roll);
Original file line number Diff line number Diff line change
@@ -4,13 +4,9 @@
import mekhq.campaign.mission.AtBContract;
import mekhq.campaign.mission.Mission;
import mekhq.campaign.personnel.Award;
import mekhq.campaign.universe.Faction;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static mekhq.campaign.personnel.autoAwards.TheatreOfWarAwards.processFaction;
import java.util.*;

public class FactionHunterAwards {
/**
@@ -21,20 +17,85 @@ public class FactionHunterAwards {
* @param awards the awards to be processed (should only include awards where item == TheatreOfWar)
*/
public static Map<Integer, List<Object>> FactionHunterAwardsProcessor(Campaign campaign, Mission mission, UUID person, List<Award> awards) {
boolean isEligible;
boolean isEligible = false;
List<Award> eligibleAwards = new ArrayList<>();

String missionFaction = ((AtBContract) mission).getEnemy().getFullName(campaign.getGameYear());
Faction missionFaction = ((AtBContract) mission).getEnemy();

for (Award award : awards) {
if (award.canBeAwarded(campaign.getPerson(person))) {
List<String> targetFactions = List.of(award.getRange().split(","));

if (!targetFactions.isEmpty()) {
// returns true if missionFaction matches the requirements of the listed targetFactions
isEligible = targetFactions
.stream()
.anyMatch(targetFaction -> processFaction(missionFaction, targetFaction));
for (String awardFaction : targetFactions) {
// does the awardFaction equal missionFaction? if so, break the loop
if ((Objects.equals(awardFaction, missionFaction.getShortName()))) {
isEligible = true;
break;
}

// does awardFaction match one of the special super-factions?
switch (awardFaction.toLowerCase()) {
case "major powers":
if (missionFaction.isMajorOrSuperPower()) {
isEligible = true;
}
break;
case "inner sphere":
if (missionFaction.isInnerSphere()) {
isEligible = true;
}
break;
case "clans":
if (missionFaction.isClan()) {
isEligible = true;
}
break;
case "periphery":
if (missionFaction.isPeriphery()) {
isEligible = true;
}
break;
case "pirate":
if (missionFaction.isPirate()) {
isEligible = true;
}
break;
case "mercenary":
if (missionFaction.isMercenary()) {
isEligible = true;
}
break;
case "independent":
if (missionFaction.isIndependent()) {
isEligible = true;
}
break;
case "deep periphery":
if (missionFaction.isDeepPeriphery()) {
isEligible = true;
}
break;
case "wob":
if (missionFaction.isWoB()) {
isEligible = true;
}
break;
case "comstar or wob":
if (missionFaction.isComStarOrWoB()) {
isEligible = true;
}
break;
default:
break;
}

// once we have one positive, there is no need to continue cycling through factions
if (isEligible) {
break;
}
}

if (isEligible) {
eligibleAwards.add(award);
Original file line number Diff line number Diff line change
@@ -146,6 +146,14 @@ public static void enrollPerson(Campaign campaign, Person person, Academy academ
public static String generateName(Academy academy, String campus) {
ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Education", MekHQ.getMHQOptions().getLocale());

if (academy.isPrepSchool()) {
if (Compute.d6(1) <= 3) {
return campus + ' ' + generateTypeChild(resources) + ' ' + resources.getString("conjoinerOf.text") + ' ' + generateSuffix(resources);
} else {
return generateTypeChild(resources) + ' ' + resources.getString("conjoinerOf.text") + ' ' + campus;
}
}

if (Compute.d6(1) <= 3) {
if (academy.isMilitary()) {
return campus + ' ' + generateMilitaryPrefix(resources) + ' ' + generateTypeAdult(resources) + ' ' + resources.getString("conjoinerOf.text") + ' ' + generateSuffix(resources);
@@ -239,6 +247,33 @@ private static String generateTypeAdult(ResourceBundle resources) {
}
}


/**
* Generates a random educational institution type from the provided ResourceBundle.
*
* @param resources the ResourceBundle containing the localized strings for the educational institution types
* @return a randomly selected educational institution type
* @throws IllegalStateException if the generated roll is unexpected
*/
private static String generateTypeChild(ResourceBundle resources) {
switch (Compute.d6(1)) {
case 1:
return resources.getString("typeAcademy.text");
case 2:
return resources.getString("typePreparatorySchool.text");
case 3:
return resources.getString("typeInstitute.text");
case 4:
return resources.getString("typeSchoolBoarding.text");
case 5:
return resources.getString("typeFinishingSchool.text");
case 6:
return resources.getString("typeSchool.text");
default:
throw new IllegalStateException("Unexpected roll in generateTypeAdult");
}
}

/**
* Processes a new day for a person in a campaign.
*
@@ -807,10 +842,12 @@ private static void processGraduation(Campaign campaign, Person person, Academy
person.setEduHighestEducation(EducationLevel.parseFromInt(educationLevel));
}

if ((academy.isReeducationCamp()) && (campaign.getCampaignOptions().isUseReeducationCamps())) {
if (!Objects.equals(person.getOriginFaction(), campaign.getFaction())) {
if (academy.isReeducationCamp()) {
if (campaign.getCampaignOptions().isUseReeducationCamps()) {
person.setOriginFaction(campaign.getFaction());
}

person.generateLoyalty(Compute.d6(4));
}
}

5 changes: 5 additions & 0 deletions MekHQ/src/mekhq/gui/CampaignGUI.java
Original file line number Diff line number Diff line change
@@ -2447,6 +2447,11 @@ public void handleDayEnding(DayEndingEvent evt) {
return;
}

if (new InvalidFactionNagDialog(getFrame(), getCampaign()).showDialog().isCancelled()) {
evt.cancel();
return;
}

if (new InsufficientAstechsNagDialog(getFrame(), getCampaign()).showDialog().isCancelled()) {
evt.cancel();
return;
11 changes: 7 additions & 4 deletions MekHQ/src/mekhq/gui/StratconPanel.java
Original file line number Diff line number Diff line change
@@ -528,7 +528,7 @@ private void drawScenarios(Graphics2D g2D) {
((scenario.getDeploymentDate() != null) ||
(scenario.isStrategicObjective() && currentTrack.getRevealedCoords().contains(currentCoords)) ||
currentTrack.isGmRevealed() || trackRevealed)) {
g2D.setColor(Color.RED);
g2D.setColor(MekHQ.getMHQOptions().getFontColorNegative());

BufferedImage scenarioImage = getImage(StratconBiomeManifest.FORCE_HOSTILE, ImageType.TerrainTile);
if (scenarioImage != null) {
@@ -836,16 +836,19 @@ private String buildSelectedHexInfo() {
if ((facility != null) && (facility.getFacilityType() != null)) {
if (facility.isStrategicObjective()) {
infoBuilder.append(String.format("<br/><span color='%s'>Contract objective located</span>",
facility.getOwner() == ForceAlignment.Allied ? "green" : "red"));
facility.getOwner() == ForceAlignment.Allied ? MekHQ.getMHQOptions().getFontColorPositiveHexColor() : MekHQ.getMHQOptions().getFontColorNegativeHexColor()));
}
infoBuilder.append((facility.getOwner() == ForceAlignment.Allied) ? "<span color='green'>" : "<span color='red'>")
infoBuilder.append("<span color='")
.append(facility.getOwner() == ForceAlignment.Allied ? MekHQ.getMHQOptions().getFontColorPositiveHexColor()
: MekHQ.getMHQOptions().getFontColorNegativeHexColor())
.append("'>")
.append("<br/>")
.append(facility.getFormattedDisplayableName())
.append("<span>");
}

} else {
infoBuilder.append("<span color='red'>Recon incomplete</span>");
infoBuilder.append("<span color='").append(MekHQ.getMHQOptions().getFontColorNegative()).append("'>Recon incomplete</span>");
}
infoBuilder.append("<br/>");

22 changes: 11 additions & 11 deletions MekHQ/src/mekhq/gui/StratconTab.java
Original file line number Diff line number Diff line change
@@ -271,9 +271,9 @@ private String buildShortStrategicObjectiveText(StratconCampaignState campaignSt

StringBuilder sb = new StringBuilder();
if (completedObjectives >= desiredObjectives) {
sb.append("<span color='green'>");
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorPositiveHexColor()).append("'>");
} else {
sb.append("<span color='red'>");
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorNegativeHexColor()).append("'>");
}

// special logic for non-independent command clauses
@@ -285,7 +285,7 @@ private String buildShortStrategicObjectiveText(StratconCampaignState campaignSt
}
}

sb.append("Strategic objectives: " + completedObjectives + "/" + desiredObjectives + " completed</span>");
sb.append("Strategic objectives: ").append(completedObjectives).append('/').append(desiredObjectives).append(" completed</span>");
return sb.toString();
}

@@ -313,16 +313,16 @@ private String buildStrategicObjectiveText(StratconCampaignState campaignState)
// special case: allied facilities can get lost at any point in time
if ((objective.getObjectiveType() == StrategicObjectiveType.AlliedFacilityControl) &&
!campaignState.allowEarlyVictory()) {
sb.append("<span color='orange'>").append(OBJECTIVE_IN_PROGRESS);
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorWarningHexColor()).append("'>").append(OBJECTIVE_IN_PROGRESS);
} else if (objectiveCompleted) {
sb.append("<span color='green'>").append(OBJECTIVE_COMPLETED);
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorPositiveHexColor()).append("'>").append(OBJECTIVE_COMPLETED);
} else if (objectiveFailed) {
sb.append("<span color='red'>").append(OBJECTIVE_FAILED);
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorNegativeHexColor()).append("'>").append(OBJECTIVE_FAILED);
} else {
sb.append("<span color='orange'>").append(OBJECTIVE_IN_PROGRESS);
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorWarningHexColor()).append("'>").append(OBJECTIVE_IN_PROGRESS);
}

sb.append(" ");
sb.append(' ');

if (!coordsRevealed && displayCoordinateData) {
sb.append("Locate and ");
@@ -368,11 +368,11 @@ private String buildStrategicObjectiveText(StratconCampaignState campaignState)
boolean contractIsActive = campaignState.getContract().isActiveOn(getCampaignGui().getCampaign().getLocalDate());

if (contractIsActive) {
sb.append("<span color='orange'>").append(OBJECTIVE_IN_PROGRESS);
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorWarningHexColor()).append("'>").append(OBJECTIVE_IN_PROGRESS);
} else if (campaignState.getVictoryPoints() > 0) {
sb.append("<span color='green'>").append(OBJECTIVE_COMPLETED);
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorPositiveHexColor()).append("'>").append(OBJECTIVE_COMPLETED);
} else {
sb.append("<span color='red'>").append(OBJECTIVE_FAILED);
sb.append("<span color='").append(MekHQ.getMHQOptions().getFontColorNegativeHexColor()).append("'>").append(OBJECTIVE_FAILED);
}

sb.append(" Maintain Campaign Victory Point count above 0 by completing required scenarios")
Original file line number Diff line number Diff line change
@@ -1518,7 +1518,7 @@ protected Optional<JPopupMenu> createPopupMenu() {
}

if (academySetNames.contains("Prestigious Academies")) {
if (!campaign.getCampaignOptions().isEnableLocalAcademies()) {
if (!campaign.getCampaignOptions().isEnablePrestigiousAcademies()) {
academySetNames.remove("Prestigious Academies");
}
}
8 changes: 8 additions & 0 deletions MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.enums.PersonnelRole;
import mekhq.campaign.personnel.enums.Profession;
import mekhq.campaign.personnel.enums.education.EducationLevel;
import mekhq.gui.CampaignGUI;
import mekhq.gui.displayWrappers.RankDisplay;
import org.apache.logging.log4j.LogManager;
@@ -357,6 +358,13 @@ private void hire(boolean isGmHire) {
person.limitSkills(age - 13);
}

// set education based on age
if (age <= 16) {
person.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD);
} else {
person.setEduHighestEducation(EducationLevel.HIGH_SCHOOL);
}

if (!campaign.recruitPerson(person, isGmHire)) {
number = 0;
} else {
9 changes: 9 additions & 0 deletions MekHQ/src/mekhq/gui/dialog/MHQOptionsDialog.java
Original file line number Diff line number Diff line change
@@ -159,6 +159,7 @@ public class MHQOptionsDialog extends AbstractMHQButtonDialog {
private JCheckBox optionUnresolvedStratConContactsNag;
private JCheckBox optionOutstandingScenariosNag;
private JCheckBox optionCargoCapacityNag;
private JCheckBox optionInvalidFactionNag;
//endregion Nag Tab

//region Miscellaneous
@@ -915,6 +916,10 @@ private JPanel createNagTab() {
optionCargoCapacityNag.setToolTipText(resources.getString("optionCargoCapacityNag.toolTipText"));
optionCargoCapacityNag.setName("optionCargoCapacityNag");

optionInvalidFactionNag = new JCheckBox(resources.getString("optionInvalidFactionNag.text"));
optionInvalidFactionNag.setToolTipText(resources.getString("optionInvalidFactionNag.toolTipText"));
optionInvalidFactionNag.setName("optionInvalidFactionNag");

// Layout the UI
final JPanel panel = new JPanel();
panel.setName("nagPanel");
@@ -938,6 +943,7 @@ private JPanel createNagTab() {
.addComponent(optionUnresolvedStratConContactsNag)
.addComponent(optionOutstandingScenariosNag)
.addComponent(optionCargoCapacityNag)
.addComponent(optionInvalidFactionNag)
);

layout.setHorizontalGroup(
@@ -955,6 +961,7 @@ private JPanel createNagTab() {
.addComponent(optionUnresolvedStratConContactsNag)
.addComponent(optionOutstandingScenariosNag)
.addComponent(optionCargoCapacityNag)
.addComponent(optionInvalidFactionNag)
);

return panel;
@@ -1215,6 +1222,7 @@ protected void okAction() {
MekHQ.getMHQOptions().setNagDialogIgnore(MHQConstants.NAG_UNRESOLVED_STRATCON_CONTACTS, optionUnresolvedStratConContactsNag.isSelected());
MekHQ.getMHQOptions().setNagDialogIgnore(MHQConstants.NAG_OUTSTANDING_SCENARIOS, optionOutstandingScenariosNag.isSelected());
MekHQ.getMHQOptions().setNagDialogIgnore(MHQConstants.NAG_CARGO_CAPACITY, optionCargoCapacityNag.isSelected());
MekHQ.getMHQOptions().setNagDialogIgnore(MHQConstants.NAG_INVALID_FACTION, optionCargoCapacityNag.isSelected());

PreferenceManager.getClientPreferences().setUserDir(txtUserDir.getText());
PreferenceManager.getInstance().save();
@@ -1330,6 +1338,7 @@ private void setInitialState() {
optionUnresolvedStratConContactsNag.setSelected(MekHQ.getMHQOptions().getNagDialogIgnore(MHQConstants.NAG_UNRESOLVED_STRATCON_CONTACTS));
optionOutstandingScenariosNag.setSelected(MekHQ.getMHQOptions().getNagDialogIgnore(MHQConstants.NAG_OUTSTANDING_SCENARIOS));
optionCargoCapacityNag.setSelected(MekHQ.getMHQOptions().getNagDialogIgnore(MHQConstants.NAG_CARGO_CAPACITY));
optionInvalidFactionNag.setSelected(MekHQ.getMHQOptions().getNagDialogIgnore(MHQConstants.NAG_INVALID_FACTION));

txtUserDir.setText(PreferenceManager.getClientPreferences().getUserDir());
spnStartGameDelay.setValue(MekHQ.getMHQOptions().getStartGameDelay());
18 changes: 10 additions & 8 deletions MekHQ/src/mekhq/gui/dialog/RetirementDefectionDialog.java
Original file line number Diff line number Diff line change
@@ -408,8 +408,8 @@ private void initComponents(boolean doRetirement) {
add(btnPanel, BorderLayout.PAGE_END);
}

private void setBonusAndShareTotals(Money bonus) {
if (bonus.isGreaterThan(hqView.getCampaign().getFinances().getBalance())) {
private void setBonusAndShareTotals(Money totalBonuses) {
if (totalBonuses.isGreaterThan(hqView.getCampaign().getFinances().getBalance())) {
lblTotal.setText("<html>" + resourceMap.getString("lblTotalBonus.text")
+ ' ' + "<font color='" + MekHQ.getMHQOptions().getFontColorNegativeHexColor() + "'>"
+ getTotalBonus().toAmountAndSymbolString() + "</font></html>");
@@ -703,18 +703,20 @@ private int getTotalShares() {

private Money getTotalBonus() {
Money retVal = Money.zero();

for (UUID id : targetRolls.keySet()) {
if (((RetirementTableModel) personnelTable.getModel()).getPayBonus(id)) {
retVal = retVal.plus(RetirementDefectionTracker.getPayoutOrBonusValue(hqView.getCampaign(),
hqView.getCampaign().getPerson(id)));

if (hqView.getCampaign().getCampaignOptions().getTurnoverFrequency().isMonthly()) {
retVal = retVal.dividedBy(12);
} else if (hqView.getCampaign().getCampaignOptions().getTurnoverFrequency().isWeekly()) {
retVal = retVal.dividedBy(52);
}
}
}

if (hqView.getCampaign().getCampaignOptions().getTurnoverFrequency().isMonthly()) {
retVal = retVal.dividedBy(12);
} else if (hqView.getCampaign().getCampaignOptions().getTurnoverFrequency().isWeekly()) {
retVal = retVal.dividedBy(52);
}

return retVal;
}

68 changes: 68 additions & 0 deletions MekHQ/src/mekhq/gui/dialog/nagDialogs/InvalidFactionNagDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2021 - The MegaMek Team. All Rights Reserved.
*
* This file is part of MekHQ.
*
* MekHQ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MekHQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MekHQ. If not, see <http://www.gnu.org/licenses/>.
*/
package mekhq.gui.dialog.nagDialogs;

import mekhq.MHQConstants;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
import mekhq.campaign.universe.Faction;
import mekhq.gui.baseComponents.AbstractMHQNagDialog;

import javax.swing.*;
import java.time.LocalDate;
import java.util.Objects;

public class InvalidFactionNagDialog extends AbstractMHQNagDialog {
private static boolean isFactionInvalid (Campaign campaign) {
Faction campaignFaction = campaign.getFaction();

if (!campaign.getFaction().validIn(campaign.getLocalDate())) {
return true;
}

// this is a special handler for FedSuns as they're the main culprit behind the issue of users having invalid factions.
// FS and LA campaigns won't trigger the above conditional, because those factions aren't technically ended when the FedSuns forms
// they just become dormant.
if (Objects.equals(campaignFaction.getShortName(), "LA")) {
// the dates picked are chosen as these are when mhq does the bulk of the faction ownership transfers
return ((campaign.getLocalDate().isAfter(LocalDate.of(3040, 1, 18)))
&& (campaign.getLocalDate().isBefore(LocalDate.of(3067, 4, 20))));
}

// this is another special handler for FedSuns as they're the main culprit behind the issue of users having invalid factions.
if (Objects.equals(campaignFaction.getShortName(), "FS")) {
return ((campaign.getLocalDate().isAfter(LocalDate.of(3040, 1, 18)))
&& (campaign.getLocalDate().isBefore(LocalDate.of(3057, 9, 18))));
}

return false;
}

//region Constructors
public InvalidFactionNagDialog(final JFrame frame, final Campaign campaign) {
super(frame, "InvalidFactionNagDialog", "InvalidFactionNagDialog.title",
"InvalidFactionNagDialog.text", campaign, MHQConstants.NAG_INVALID_FACTION);
}

//endregion Constructors
@Override
protected boolean checkNag() {
return !MekHQ.getMHQOptions().getNagDialogIgnore(getKey()) && (isFactionInvalid(getCampaign()));
}
}
2 changes: 1 addition & 1 deletion MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
Original file line number Diff line number Diff line change
@@ -8491,7 +8491,7 @@ public void updateOptions() {
}
campaign.setLocalDate(date);

if (campaign.getCampaignStartDate() == null) {
if ((campaign.getCampaignStartDate() == null) || (campaign.getCampaignStartDate().isAfter(campaign.getLocalDate()))) {
campaign.setCampaignStartDate(date);
}
// Ensure that the MegaMek year GameOption matches the campaign year
6 changes: 3 additions & 3 deletions MekHQ/src/mekhq/gui/panes/UnitMarketPane.java
Original file line number Diff line number Diff line change
@@ -198,7 +198,7 @@ protected Component createLeftComponent() {

final JScrollPane marketTableScrollPane = createMarketTablePane();

final JLabel lblBlackMarketWarning = new JLabel(resources.getString("lblBlackMarketWarning.text"));
final JLabel lblMarketDescriptions = new JLabel(resources.getString("lblMarketDescriptions.text"));

// Layout the UI
JPanel panel = new JPanel();
@@ -215,7 +215,7 @@ protected Component createLeftComponent() {
.addComponent(filtersPanel)
.addComponent(getEntityImagePanel(), Alignment.LEADING))
.addComponent(marketTableScrollPane)
.addComponent(lblBlackMarketWarning)
.addComponent(lblMarketDescriptions)
);

layout.setHorizontalGroup(
@@ -224,7 +224,7 @@ protected Component createLeftComponent() {
.addComponent(filtersPanel)
.addComponent(getEntityImagePanel()))
.addComponent(marketTableScrollPane)
.addComponent(lblBlackMarketWarning, Alignment.TRAILING)
.addComponent(lblMarketDescriptions, Alignment.TRAILING)
);
return panel;
}
5 changes: 2 additions & 3 deletions MekHQ/src/mekhq/gui/view/PersonViewPanel.java
Original file line number Diff line number Diff line change
@@ -1468,8 +1468,7 @@ private JPanel fillSkills() {
firsty++;
}

if ((campaign.getCampaignOptions().isUseFatigue())
&& (person.getEffectiveFatigue(campaign) > 0)) {
if ((campaign.getCampaignOptions().isUseFatigue()) && (person.getFatigue() > 0)) {
lblFatigue1.setName("lblFatigue1");
lblFatigue1.setText(resourceMap.getString("lblFatigue1.text"));
gridBagConstraints = new GridBagConstraints();
@@ -1481,7 +1480,7 @@ private JPanel fillSkills() {

StringBuilder fatigueDisplay = new StringBuilder();
int effectiveFatigue = person.getEffectiveFatigue(campaign);
int fatigueTurnoverModifier = MathUtility.clamp(((person.getFatigue() - 1) / 4) - 1, 0, 3);
int fatigueTurnoverModifier = MathUtility.clamp(((person.getEffectiveFatigue(campaign) - 1) / 4) - 1, 0, 3);

fatigueDisplay.append(person.getFatigue());

0 comments on commit 24d745c

Please sign in to comment.