Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Contract Automation #5172

Merged
merged 7 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MekHQ/resources/mekhq/resources/Campaign.properties
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,4 @@ bonusPartLog.text=Bonus part used to acquire 1x
newAtBScenario.format=New scenario "{0}" will occur on {1}.
atbScenarioToday.format=Scenario "{0}" is today, deploy a force from your TOE!
atbScenarioTodayWithForce.format=Scenario "{0}" is today, {1} has been deployed!
generalFallbackAddress.text=Commander
34 changes: 34 additions & 0 deletions MekHQ/resources/mekhq/resources/ContractAutomation.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# General
generalTitle.text=++ INCOMING TRANSMISSION ++
generalConfirm.text=Accept
generalDecline.text=Decline
generalNonClan.text=The %s

# Messages
mothballDescription.text=%s, our employer has offered to assist our personnel in getting our\
\ equipment ready for transport.\
<br>\
<br>Prior to loading, all equipment in our TO&E will be <b>mothballed</b>. This will prevent us\
\ needing to maintain it while in transit and the units will be <b>unmothballed</b> prior to\
\ arrival. Equipment outside our TO&E will be unaffected.\
<br>\
<br>Will we be accepting their offer?\
<br>\
<br>If we decline, you will still be able to manually order mothballing of equipment, but this\
\ will need to be arranged by right-clicking the unit in the Hangar panel of your command console,\
\ and selecting 'mothball.' Our techs will then take care of it as time becomes available.

transitDescription.text=Our target system is <b>%s</b>. %s has already calculated the best route\
\ for us.\
<br>\
<br>This journey will take us approximately <b>%s</b> days and cost <b>%s</b>. Would you like to\
\ accept this route and begin transit?\
<br>\
<br>If we decline, you will need to manually order route calculation from the Interstellar Map.\
\ This can be done by selecting the target system in your Briefing Room, followed by 'Calculate\
\ Jump Path' and 'Begin Transit.'

# Reports
mothballingFailed.text=%s was not eligible to be automatically mothballed. Units cannot be\
\ destroyed, refitting, undergoing repairs, mid-mothball, or already mothballed.
activationFailed.text=%s could not be automatically un-mothballed.
46 changes: 46 additions & 0 deletions MekHQ/src/mekhq/campaign/Campaign.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
import java.util.Map.Entry;
import java.util.stream.Collectors;

import static mekhq.campaign.market.contractMarket.ContractAutomation.performAutomatedActivation;
import static mekhq.campaign.personnel.backgrounds.BackgroundsController.randomMercenaryCompanyNameGenerator;
import static mekhq.campaign.personnel.education.EducationController.getAcademy;
import static mekhq.campaign.personnel.turnoverAndRetention.RetirementDefectionTracker.Payout.isBreakingContract;
Expand Down Expand Up @@ -268,6 +269,7 @@ public class Campaign implements ITechManager {
private final Quartermaster quartermaster;
private StoryArc storyArc;
private FameAndInfamyController fameAndInfamy;
private List<Unit> automatedMothballUnits;

private final transient ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Campaign",
MekHQ.getMHQOptions().getLocale());
Expand Down Expand Up @@ -335,6 +337,7 @@ public Campaign() {
quartermaster = new Quartermaster(this);
fieldKitchenWithinCapacity = false;
fameAndInfamy = new FameAndInfamyController();
automatedMothballUnits = new ArrayList<>();
}

/**
Expand Down Expand Up @@ -3661,6 +3664,12 @@ && getLocation().getJumpPath().getLastSystem().getId().equals(contract.getSystem
}
}

if (Objects.equals(location.getCurrentSystem(), contract.getSystem())) {
if (!automatedMothballUnits.isEmpty()) {
performAutomatedActivation(this);
}
}

for (final Scenario scenario : contract.getCurrentAtBScenarios()) {
if ((scenario.getDate() != null) && scenario.getDate().isBefore(getLocalDate())) {
if (getCampaignOptions().isUseStratCon() && (scenario instanceof AtBDynamicScenario)) {
Expand Down Expand Up @@ -5313,6 +5322,14 @@ public FameAndInfamyController getFameAndInfamy() {
return fameAndInfamy;
}

public List<Unit> getAutomatedMothballUnits() {
return automatedMothballUnits;
}

public void setAutomatedMothballUnits(List<Unit> automatedMothballUnits) {
this.automatedMothballUnits = automatedMothballUnits;
}

public void writeToXML(final PrintWriter pw) {
int indent = 0;

Expand Down Expand Up @@ -5495,6 +5512,12 @@ public void writeToXML(final PrintWriter pw) {

retirementDefectionTracker.writeToXML(pw, indent);

MHQXMLUtility.writeSimpleXMLOpenTag(pw, indent++, "automatedMothballUnits");
for (Unit unit : automatedMothballUnits) {
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "mothballedUnit", unit.getId());
}
MHQXMLUtility.writeSimpleXMLCloseTag(pw, --indent, "automatedMothballUnits");

// Customised planetary events
MHQXMLUtility.writeSimpleXMLOpenTag(pw, indent++, "customPlanetaryEvents");
for (PlanetarySystem psystem : Systems.getInstance().getSystems().values()) {
Expand Down Expand Up @@ -8377,4 +8400,27 @@ public boolean useVariableTechLevel() {
public boolean showExtinct() {
return !campaignOptions.isDisallowExtinctStuff();
}

/**
* Gets a string to use for addressing the commander.
* If no commander is flagged, returns a default address.
*
* @return The title of the commander, or a default string if no commander.
*/
public String getCommanderAddress() {
Person commander = getFlaggedCommander();

if (commander == null) {
return resources.getString("generalFallbackAddress.text");
}

String commanderRank = commander.getRankName();

if (commanderRank.equalsIgnoreCase("None") || commanderRank.isBlank()) {
return commander.getFullName();
}

return commanderRank;
}

}
39 changes: 37 additions & 2 deletions MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
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;
Expand Down Expand Up @@ -284,6 +284,8 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException {
} else if (xn.equalsIgnoreCase("retirementDefectionTracker")) {
retVal.setRetirementDefectionTracker(
RetirementDefectionTracker.generateInstanceFromXML(wn, retVal));
} else if (xn.equalsIgnoreCase("automatedMothballUnits")) {
retVal.setAutomatedMothballUnits(processAutomatedMothballNodes(wn, retVal));
} else if (xn.equalsIgnoreCase("shipSearchStart")) {
retVal.setShipSearchStart(MHQXMLUtility.parseDate(wn.getTextContent().trim()));
} else if (xn.equalsIgnoreCase("shipSearchType")) {
Expand Down Expand Up @@ -937,6 +939,39 @@ private static void processFameAndInfamyNodes(Campaign relativeValue, Node worki
FameAndInfamyController.parseFromXML(workingNode.getChildNodes(), relativeValue);
}

private static List<Unit> processAutomatedMothballNodes(Node workingNode, Campaign campaign) {
logger.info("Loading Automated Mothball Nodes from XML...");

List<Unit> mothballedUnits = new ArrayList<>();

NodeList workingList = workingNode.getChildNodes();
for (int x = 0; x < workingList.getLength(); x++) {
Node childNode = workingList.item(x);

// If it's not an element node, we ignore it.
if (childNode.getNodeType() != Node.ELEMENT_NODE) {
continue;
}

if (!childNode.getNodeName().equalsIgnoreCase("mothballedUnit")) {
logger.error("Unknown node type not loaded in Automated Mothball nodes: "
+ childNode.getNodeName());
continue;
}

Unit unit = campaign.getUnit(UUID.fromString(childNode.getTextContent()));

if (unit == null) {
logger.error("Unknown UUID: " + childNode.getTextContent());
}

mothballedUnits.add(unit);
}

logger.info("Load Automated Mothball Nodes Complete!");
return mothballedUnits;
}

private static void processSpecialAbilityNodes(Campaign retVal, Node wn, Version version) {
logger.info("Loading Special Ability Nodes from XML...");

Expand Down
Loading