Skip to content

Commit e0d2450

Browse files
authored
Merge pull request #7251 from IllianiBird/factionStandingCommandCircuit
Improvement: Implemented Command Circuit Travel via GM Mode or Faction Standings
2 parents 5493b1a + 1355e02 commit e0d2450

File tree

14 files changed

+447
-123
lines changed

14 files changed

+447
-123
lines changed

MekHQ/resources/mekhq/resources/CampaignGUI.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ btnBeginTransit.text=Begin Transit
204204
chkAvoidAbandonedSystems.text=Avoid Empty Systems
205205
chkAvoidAbandonedSystems.toolTipText=Pathfinding will avoid abandoned systems. In-universe travelling in empty systems\
206206
\ was avoided whenever possible.
207+
chkUseCommandCircuits.text=Always Use Command Circuits (GM)
208+
chkUseCommandCircuits.toolTipText=Reduces all JumpShip recharge times to 10 hours (or less). While this is intended \
209+
to represent the use of Command Circuits, it can also be used to reduce travel times resulting in a more fastpaced \
210+
campaign.
207211
lblFindPlanet.text=Find Planet:
208212
panAssignedPatient.title=Assigned Patients
209213
panUnassignedPatient.title=Unassigned Patients

MekHQ/src/mekhq/campaign/Campaign.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ public class Campaign implements ITechManager {
358358

359359
private CurrentLocation location;
360360
private boolean isAvoidingEmptySystems;
361+
private boolean isOverridingCommandCircuitRequirements;
361362

362363
private final News news;
363364

@@ -458,6 +459,7 @@ public Campaign() {
458459
CurrencyManager.getInstance().setCampaign(this);
459460
location = new CurrentLocation(Systems.getInstance().getSystems().get("Galatea"), 0);
460461
isAvoidingEmptySystems = true;
462+
isOverridingCommandCircuitRequirements = false;
461463
currentReport = new ArrayList<>();
462464
currentReportHTML = "";
463465
newReports = new ArrayList<>();
@@ -614,6 +616,14 @@ public void setIsAvoidingEmptySystems(boolean isAvoidingEmptySystems) {
614616
this.isAvoidingEmptySystems = isAvoidingEmptySystems;
615617
}
616618

619+
public boolean isOverridingCommandCircuitRequirements() {
620+
return isOverridingCommandCircuitRequirements;
621+
}
622+
623+
public void setIsOverridingCommandCircuitRequirements(boolean isOverridingCommandCircuitRequirements) {
624+
this.isOverridingCommandCircuitRequirements = isOverridingCommandCircuitRequirements;
625+
}
626+
617627
/**
618628
* Returns the Hiring Hall level from the force's current system on the current date. If there is no hiring hall
619629
* present, the level is HiringHallLevel.NONE.
@@ -6766,6 +6776,10 @@ public void writeToXML(final PrintWriter writer) {
67666776
finances.writeToXML(writer, indent);
67676777
location.writeToXML(writer, indent);
67686778
MHQXMLUtility.writeSimpleXMLTag(writer, indent, "isAvoidingEmptySystems", isAvoidingEmptySystems);
6779+
MHQXMLUtility.writeSimpleXMLTag(writer,
6780+
indent,
6781+
"isOverridingCommandCircuitRequirements",
6782+
isOverridingCommandCircuitRequirements);
67696783
shoppingList.writeToXML(writer, indent);
67706784
MHQXMLUtility.writeSimpleXMLOpenTag(writer, indent++, "kills");
67716785
for (List<Kill> kills : kills.values()) {
@@ -7060,9 +7074,14 @@ public JumpPath calculateJumpPath(PlanetarySystem start, PlanetarySystem end) {
70607074
// A* search
70617075
final int MAX_JUMPS = 10000;
70627076
for (int jumps = 0; jumps < MAX_JUMPS; jumps++) {
7063-
// Get current node's information
70647077
PlanetarySystem currentSystem = systemsInstance.getSystemById(current);
7065-
double currentG = scoreG.get(current) + currentSystem.getRechargeTime(getLocalDate());
7078+
7079+
boolean isUseCommandCircuits =
7080+
FactionStandingUtilities.isUseCommandCircuit(isOverridingCommandCircuitRequirements, gmMode,
7081+
campaignOptions.isUseFactionStandingCommandCircuitSafe(), factionStandings, getActiveAtBContracts());
7082+
7083+
// Get current node's information
7084+
double currentG = scoreG.get(current) + currentSystem.getRechargeTime(getLocalDate(), isUseCommandCircuits);
70667085
final String localCurrent = current;
70677086

70687087
// Explore neighbors

MekHQ/src/mekhq/campaign/CampaignOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ public static String getTechLevelName(final int techLevel) {
652652
private boolean useFactionStandingNegotiation;
653653
private boolean useFactionStandingResupply;
654654
private boolean useFactionStandingCommandCircuit;
655-
private boolean useFactionStandingOutlawed;
655+
private boolean useFactionStandingOutlawed; // TODO
656656
private boolean useFactionStandingBatchallRestrictions;
657657
private boolean useFactionStandingRecruitment;
658658
private boolean useFactionStandingBarracksCosts;

MekHQ/src/mekhq/campaign/CurrentLocation.java

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import mekhq.campaign.universe.Planet;
5959
import mekhq.campaign.universe.PlanetarySystem;
6060
import mekhq.campaign.universe.Systems;
61+
import mekhq.campaign.universe.factionStanding.FactionStandingUtilities;
6162
import mekhq.gui.baseComponents.immersiveDialogs.ImmersiveDialogSimple;
6263
import mekhq.utilities.MHQXMLUtility;
6364
import mekhq.utilities.ReportingUtilities;
@@ -158,56 +159,83 @@ private boolean pickJumpPoint(LocalDate now) {
158159
return randomInt(2) == 1;
159160
}
160161

162+
/**
163+
* Use {@link #getReport(LocalDate, Money, boolean)} instead
164+
*/
165+
@Deprecated(since = "0.50.07", forRemoval = true)
161166
public String getReport(LocalDate date, Money jumpCost) {
162-
StringBuilder sb = new StringBuilder();
163-
sb.append("<html>")
167+
return getReport(date, jumpCost, false);
168+
}
169+
170+
/**
171+
* Generates a detailed status report for the current location and travel state.
172+
*
173+
* <p>The report includes:</p>
174+
* <ul>
175+
* <li>The current system and position, indicating if on a planet, at a jump point (with recharge status),
176+
* in transit from a planet, or close to a jump point.</li>
177+
* <li>Travel progress, including the destination system, remaining jumps, or if already at the destination.</li>
178+
* <li>The estimated jump cost for the current journey.</li>
179+
* </ul>
180+
*
181+
* <p>The report is formatted as HTML suitable for display in GUI components.</p>
182+
*
183+
* @param date the current {@link LocalDate} for context-sensitive names and status
184+
* @param jumpCost the estimated jump cost as a {@link Money} value
185+
* @param isUseCommandCircuit whether the command circuit option is enabled
186+
*
187+
* @return a formatted HTML string representing the travel and location status report
188+
*/
189+
public String getReport(LocalDate date, Money jumpCost, boolean isUseCommandCircuit) {
190+
double currentRechargeTime = currentSystem.getRechargeTime(date, isUseCommandCircuit);
191+
192+
StringBuilder report = new StringBuilder();
193+
report.append("<html>")
164194
// First Line
165195
.append("In ").append(currentSystem.getPrintableName(date)).append(' ');
166196

167197
if (isOnPlanet()) {
168-
sb.append("on planet ").append(getPlanet().getPrintableName(date));
198+
report.append("on planet ").append(getPlanet().getPrintableName(date));
169199
} else if (isAtJumpPoint()) {
170-
sb.append("at jump point");
171-
if (!Double.isInfinite(currentSystem.getRechargeTime(date))) {
172-
sb.append(" (Jumpship ")
200+
report.append("at jump point");
201+
if (!Double.isInfinite(currentRechargeTime)) {
202+
report.append(" (Jumpship ")
173203
.append(String.format(Locale.ROOT,
174204
"%.0f",
175-
(100.0 * rechargeTime) / currentSystem.getRechargeTime(date)))
205+
(100.0 * rechargeTime) / currentRechargeTime))
176206
.append("% charged)");
177207
}
178208
} else {
179209
if ((null != jumpPath) && (currentSystem == jumpPath.getLastSystem())) {
180-
sb.append(String.format(Locale.ROOT, "%.2f", getTransitTime())).append(" days from planet");
210+
report.append(String.format(Locale.ROOT, "%.2f", getTransitTime())).append(" days from planet");
181211
} else {
182212
double timeToJP = currentSystem.getTimeToJumpPoint(1.0) - getTransitTime();
183-
sb.append(String.format(Locale.ROOT, "%.2f", timeToJP)).append(" days from jump point");
213+
report.append(String.format(Locale.ROOT, "%.2f", timeToJP)).append(" days from jump point");
184214
}
185-
186215
}
187216

188-
sb.append("<br/>");
217+
report.append("<br/>");
189218

190219
// Second Line
191-
192220
if ((null != jumpPath) && !jumpPath.isEmpty()) {
193-
sb.append("Traveling to ").append(jumpPath.getLastSystem().getPrintableName(date)).append(": ");
221+
report.append("Traveling to ").append(jumpPath.getLastSystem().getPrintableName(date)).append(": ");
194222
if (jumpPath.getJumps() > 0) {
195-
sb.append(jumpPath.getJumps())
223+
report.append(jumpPath.getJumps())
196224
.append(jumpPath.getJumps() == 1 ? " jump remaining" : " jumps remaining");
197225
} else {
198-
sb.append("In destination system");
226+
report.append("In destination system");
199227
}
200228
} else {
201-
sb.append("Not traveling");
229+
report.append("Not traveling");
202230
}
203231

204-
sb.append("<br/>");
232+
report.append("<br/>");
205233

206234
// Third Line
207-
sb.append("Estimated Jump Cost: ").append(jumpCost.toAmountString()).append(" C-Bills<br><br>");
235+
report.append("Estimated Jump Cost: ").append(jumpCost.toAmountString()).append(" C-Bills<br><br>");
208236

209-
sb.append("</html>");
210-
return sb.toString();
237+
report.append("</html>");
238+
return report.toString();
211239
}
212240

213241
public JumpPath getJumpPath() {
@@ -226,7 +254,11 @@ public void setJumpPath(JumpPath path) {
226254
* @return True if the JumpShip has to spend time recharging, otherwise false.
227255
*/
228256
public boolean isRecharging(Campaign campaign) {
229-
return currentSystem.getRechargeTime(campaign.getLocalDate()) > 0;
257+
boolean isUseCommandCircuit = FactionStandingUtilities.isUseCommandCircuit(campaign.isOverridingCommandCircuitRequirements(),
258+
campaign.isGM(), campaign.getCampaignOptions().isUseFactionStandingCommandCircuitSafe(),
259+
campaign.getFactionStandings(), campaign.getActiveAtBContracts());
260+
261+
return currentSystem.getRechargeTime(campaign.getLocalDate(), isUseCommandCircuit) > 0;
230262
}
231263

232264
/**
@@ -235,7 +267,11 @@ public boolean isRecharging(Campaign campaign) {
235267
* @param campaign The campaign object which owns the JumpShip.
236268
*/
237269
public void setRecharged(Campaign campaign) {
238-
rechargeTime = currentSystem.getRechargeTime(campaign.getLocalDate());
270+
boolean isUseCommandCircuit = FactionStandingUtilities.isUseCommandCircuit(campaign.isOverridingCommandCircuitRequirements(),
271+
campaign.isGM(), campaign.getCampaignOptions().isUseFactionStandingCommandCircuitSafe(),
272+
campaign.getFactionStandings(), campaign.getActiveAtBContracts());
273+
274+
rechargeTime = currentSystem.getRechargeTime(campaign.getLocalDate(), isUseCommandCircuit);
239275
}
240276

241277
/**
@@ -244,10 +280,14 @@ public void setRecharged(Campaign campaign) {
244280
public void newDay(Campaign campaign) {
245281
final boolean wasTraveling = !isOnPlanet();
246282

283+
boolean isUseCommandCircuit = FactionStandingUtilities.isUseCommandCircuit(campaign.isOverridingCommandCircuitRequirements(),
284+
campaign.isGM(), campaign.getCampaignOptions().isUseFactionStandingCommandCircuitSafe(),
285+
campaign.getFactionStandings(), campaign.getActiveAtBContracts());
286+
247287
// recharge even if there is no jump path
248288
// because JumpShips don't go anywhere
249289
double hours = 24.0;
250-
double neededRechargeTime = currentSystem.getRechargeTime(campaign.getLocalDate());
290+
double neededRechargeTime = currentSystem.getRechargeTime(campaign.getLocalDate(), isUseCommandCircuit);
251291
double usedRechargeTime = Math.min(hours, neededRechargeTime - rechargeTime);
252292
if (usedRechargeTime > 0) {
253293
campaign.addReport("JumpShips spent " +

MekHQ/src/mekhq/campaign/JumpPath.java

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
*
2626
* Catalyst Game Labs and the Catalyst Game Labs logo are trademarks of
2727
* InMediaRes Productions, LLC.
28+
*
29+
* MechWarrior Copyright Microsoft Corporation. MekHQ was created under
30+
* Microsoft's "Game Content Usage Rules"
31+
* <https://www.xbox.com/en-US/developers/rules> and it is not endorsed by or
32+
* affiliated with Microsoft.
2833
*/
2934
package mekhq.campaign;
3035

@@ -33,12 +38,11 @@
3338
import java.util.ArrayList;
3439
import java.util.List;
3540

36-
import org.w3c.dom.Node;
37-
import org.w3c.dom.NodeList;
38-
3941
import megamek.logging.MMLogger;
4042
import mekhq.campaign.universe.PlanetarySystem;
4143
import mekhq.utilities.MHQXMLUtility;
44+
import org.w3c.dom.Node;
45+
import org.w3c.dom.NodeList;
4246

4347
/**
4448
* This is an array list of planets for a jump path, from which we can derive
@@ -104,7 +108,26 @@ public double getEndTime() {
104108
return endTime;
105109
}
106110

111+
/**
112+
* Use {@link #getTotalRechargeTime(LocalDate, boolean)} instead
113+
*/
107114
public double getTotalRechargeTime(LocalDate when) {
115+
return getTotalRechargeTime(when, false);
116+
}
117+
118+
/**
119+
* Calculates the total recharge time, in days, required to complete a journey along the path of planetary systems.
120+
*
121+
* <p>This method iterates through each system in the path, excluding the first and last systems, and sums the
122+
* rounded-up recharge time (in hours) for each waypoint. The total is then converted from hours to days.</p>
123+
*
124+
* @param when the date to use for determining recharge times at each system
125+
* @param isUseCommandCircuit {@code true} if command circuits are being utilized during the journey; may affect
126+
* recharge efficiency or duration
127+
*
128+
* @return the total recharge time for the route, expressed in days
129+
*/
130+
public double getTotalRechargeTime(LocalDate when, boolean isUseCommandCircuit) {
108131
int rechargeTime = 0;
109132
for (PlanetarySystem system : path) {
110133
if (system.equals(getFirstSystem())) {
@@ -113,7 +136,7 @@ public double getTotalRechargeTime(LocalDate when) {
113136
if (system.equals(getLastSystem())) {
114137
continue;
115138
}
116-
rechargeTime += (int) Math.ceil(system.getRechargeTime(when));
139+
rechargeTime += (int) Math.ceil(system.getRechargeTime(when, isUseCommandCircuit));
117140
}
118141
return rechargeTime / 24.0;
119142
}
@@ -122,8 +145,36 @@ public int getJumps() {
122145
return size() - 1;
123146
}
124147

148+
/**
149+
* Use {@link #getTotalTime(LocalDate, double, boolean)} instead
150+
* <p>
151+
* Used in Legacy AtB tests.
152+
*/
153+
@Deprecated(since = "0.50.07", forRemoval = false)
125154
public double getTotalTime(LocalDate when, double currentTransit) {
126-
return getTotalRechargeTime(when) + getStartTime(currentTransit) + getEndTime();
155+
return getTotalTime(when, currentTransit, false);
156+
}
157+
158+
/**
159+
* Calculates the total journey time for the path of planetary systems, including recharge, start, and end times.
160+
*
161+
* <p>This method sums three parts:</p>
162+
* <ul>
163+
* <li>Recharge time for intermediate planetary systems (in days), accounting for possible command circuit usage</li>
164+
* <li>Start time, based on the current transit</li>
165+
* <li>End time, representing final approach or operations at the destination</li>
166+
* </ul>
167+
*
168+
* @param when the date to use for all time calculations in the journey
169+
* @param currentTransit the remaining fraction of the current transit (in days or hours, depending on
170+
* context)
171+
* @param isUseCommandCircuit {@code true} if command circuits are used for the journey, which may affect recharge
172+
* time calculations
173+
*
174+
* @return the total time required for the journey, in days
175+
*/
176+
public double getTotalTime(LocalDate when, double currentTransit, boolean isUseCommandCircuit) {
177+
return getTotalRechargeTime(when, isUseCommandCircuit) + getStartTime(currentTransit) + getEndTime();
127178
}
128179

129180
public void addSystem(PlanetarySystem s) {

0 commit comments

Comments
 (0)