Skip to content

Commit

Permalink
Merge pull request #5692 from IllianiCBT/stratCon_undeploy
Browse files Browse the repository at this point in the history
Removed Undeploy Option (again); Added Reset Scenario Deployment Option
  • Loading branch information
Sleet01 authored Jan 9, 2025
2 parents ff53b77 + c8ce5b5 commit d187832
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 17 deletions.
75 changes: 71 additions & 4 deletions MekHQ/src/mekhq/campaign/stratcon/StratconScenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@
import mekhq.campaign.Campaign;
import mekhq.campaign.event.DeploymentChangedEvent;
import mekhq.campaign.force.Force;
import mekhq.campaign.mission.AtBContract;
import mekhq.campaign.mission.AtBDynamicScenario;
import mekhq.campaign.mission.ScenarioForceTemplate;
import mekhq.campaign.mission.ScenarioTemplate;
import mekhq.campaign.mission.*;
import mekhq.campaign.unit.Unit;

import java.time.LocalDate;
import java.util.*;

import static mekhq.campaign.stratcon.StratconScenario.ScenarioState.UNRESOLVED;

/**
* Class that handles scenario metadata and interaction at the StratCon level
* @author NickAragua
Expand Down Expand Up @@ -456,4 +455,72 @@ public void setAvailableLeadershipBudget(int leadershipPointsUsed) {

return null;
}

/**
* Resets the state of the current scenario for the given campaign. This includes updating the
* scenario state, clearing associated forces and units, and detaching them from the scenario.
* It also ensures that the scenario's backing contract and campaign state remain consistent.
*
* @param campaign The {@link Campaign} object for which the scenario needs to be reset.
* <p>
* The method performs the following:
* <ul>
* <li>Resets the scenario's state to {@code UNRESOLVED}.</li>
* <li>Clears any leadership budget and failed reinforcements associated with the scenario.</li>
* <li>Resets the list of primary forces linked to the scenario.</li>
* <li>If the scenario has a backing {@link AtBDynamicScenario}, it fetches the corresponding contract and
* {@link StratconCampaignState} to handle associated track and force assignments:</li>
* <li>-- Clears all forces and units assigned to the scenario, detaching them appropriately.</li>
* <li>-- Undeploys all units and clears scenario IDs for the forces and units associated with the scenario.</li>
* <li>-- Unassigns the force from the {@link StratconTrackState} and triggers a
* {@link DeploymentChangedEvent} for updates.</li>
* </ul>
*
* <strong>Note:</strong> If the backing scenario ID is invalid or the contract is null, the
* method exits early and performs no further actions.
*/
public void resetScenario(Campaign campaign) {
setCurrentState(UNRESOLVED);
setAvailableLeadershipBudget(0);
setFailedReinforcements(new HashSet<>());
setPrimaryForceIDs(new ArrayList<>());

int backingScenarioId = getBackingScenarioID();
Scenario backingScenario = campaign.getScenario(backingScenarioId);

if (backingScenarioId != -1 && backingScenario instanceof AtBDynamicScenario) {
AtBContract contract = ((AtBDynamicScenario) backingScenario).getContract(campaign);
if (contract == null) {
return;
}
StratconCampaignState campaignState = contract.getStratconCampaignState();

StratconTrackState track = getTrackForScenario(campaign, campaignState);
for (Force force : campaign.getAllForces()) {
if (force.getScenarioId() == backingScenarioId) {
force.clearScenarioIds(campaign, true);
backingScenario.removeForce(force.getId());

for (UUID uid : force.getAllUnits(false)) {
Unit unit = campaign.getUnit(uid);
if (unit != null) {
backingScenario.removeUnit(unit.getId());
unit.undeploy();
}
}

track.unassignForce(force.getId());
MekHQ.triggerEvent(new DeploymentChangedEvent(force, backingScenario));
}
}

for (Unit unit : campaign.getUnits()) {
if (unit.getScenarioId() == backingScenarioId) {
backingScenario.removeUnit(unit.getId());
unit.undeploy();
MekHQ.triggerEvent(new DeploymentChangedEvent(unit, backingScenario));
}
}
}
}
}
13 changes: 13 additions & 0 deletions MekHQ/src/mekhq/campaign/stratcon/StratconTrackState.java
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,19 @@ public void unassignForce(int forceID) {
}
}

/**
* Handles the unassignment of a force from this track.
*/
public void unassignUnit(int forceID) {
if (assignedForceCoords.containsKey(forceID)) {
assignedCoordForces.get(assignedForceCoords.get(forceID)).remove(forceID);
assignedForceCoords.remove(forceID);
assignedForceReturnDates.remove(forceID);
removeStickyForce(forceID);
getAssignedForceReturnDatesForStorage().remove(forceID);
}
}

/**
* Restores the look up table of force IDs to return dates
*/
Expand Down
34 changes: 27 additions & 7 deletions MekHQ/src/mekhq/gui/StratconPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class StratconPanel extends JPanel implements ActionListener {
private static final String RCLICK_COMMAND_CAPTURE_FACILITY = "CaptureFacility";
private static final String RCLICK_COMMAND_ADD_FACILITY = "AddFacility";
private static final String RCLICK_COMMAND_REMOVE_SCENARIO = "RemoveScenario";
private static final String RCLICK_COMMAND_RESET_DEPLOYMENT = "ResetDeployment";

/**
* What to do when drawing a hex
Expand Down Expand Up @@ -172,7 +173,7 @@ private void buildRightClickMenu(StratconCoords coords) {
// except if there is already a non-cloaked scenario here.
if (StratconRulesManager.canManuallyDeployAnyForce(coords, currentTrack, campaignState.getContract())) {
menuItemManageForceAssignments = new JMenuItem();
menuItemManageForceAssignments.setText("Manage Force Assignment");
menuItemManageForceAssignments.setText("Manage Deployment");
menuItemManageForceAssignments.setActionCommand(RCLICK_COMMAND_MANAGE_FORCES);
menuItemManageForceAssignments.addActionListener(this);
rightClickMenu.add(menuItemManageForceAssignments);
Expand All @@ -184,7 +185,13 @@ private void buildRightClickMenu(StratconCoords coords) {

if (backingScenario != null && !backingScenario.isCloaked()) {
menuItemManageScenario = new JMenuItem();
menuItemManageScenario.setText("Manage Reinforcements");

if (scenario.getCurrentState().equals(UNRESOLVED)) {
menuItemManageScenario.setText("Manage Deployment");
} else {
menuItemManageScenario.setText("Manage Reinforcements");
}

menuItemManageScenario.setActionCommand(RCLICK_COMMAND_MANAGE_FORCES);
menuItemManageScenario.addActionListener(this);
rightClickMenu.add(menuItemManageScenario);
Expand All @@ -209,26 +216,26 @@ private void buildRightClickMenu(StratconCoords coords) {
rightClickMenu.addSeparator();

menuItemGMReveal = new JMenuItem();
menuItemGMReveal.setText(currentTrack.isGmRevealed() ? "Hide Sector" : "Reveal Sector");
menuItemGMReveal.setText(currentTrack.isGmRevealed() ? "Hide Sector (GM)" : "Reveal Sector (GM)");
menuItemGMReveal.setActionCommand(RCLICK_COMMAND_REVEAL_TRACK);
menuItemGMReveal.addActionListener(this);
rightClickMenu.add(menuItemGMReveal);

if (currentTrack.getFacility(coords) != null) {
menuItemRemoveFacility = new JMenuItem();
menuItemRemoveFacility.setText("Remove Facility");
menuItemRemoveFacility.setText("Remove Facility (GM)");
menuItemRemoveFacility.setActionCommand(RCLICK_COMMAND_REMOVE_FACILITY);
menuItemRemoveFacility.addActionListener(this);
rightClickMenu.add(menuItemRemoveFacility);

menuItemSwitchOwner = new JMenuItem();
menuItemSwitchOwner.setText("Switch Owner");
menuItemSwitchOwner.setText("Switch Owner (GM)");
menuItemSwitchOwner.setActionCommand(RCLICK_COMMAND_CAPTURE_FACILITY);
menuItemSwitchOwner.addActionListener(this);
rightClickMenu.add(menuItemSwitchOwner);
} else {
menuItemAddFacility = new JMenu();
menuItemAddFacility.setText("Add Facility");
menuItemAddFacility.setText("Add Facility (GM)");

JMenu menuItemAddAlliedFacility = new JMenu();
menuItemAddAlliedFacility.setText("Allied");
Expand Down Expand Up @@ -261,10 +268,16 @@ private void buildRightClickMenu(StratconCoords coords) {

if (scenario != null) {
JMenuItem removeScenarioItem = new JMenuItem();
removeScenarioItem.setText("Remove Scenario");
removeScenarioItem.setText("Remove Scenario (GM)");
removeScenarioItem.setActionCommand(RCLICK_COMMAND_REMOVE_SCENARIO);
removeScenarioItem.addActionListener(this);
rightClickMenu.add(removeScenarioItem);

JMenuItem resetDeploymentItem = new JMenuItem();
resetDeploymentItem.setText("Reset Deployment (GM)");
resetDeploymentItem.setActionCommand(RCLICK_COMMAND_RESET_DEPLOYMENT);
resetDeploymentItem.addActionListener(this);
rightClickMenu.add(resetDeploymentItem);
}
}
}
Expand Down Expand Up @@ -1081,6 +1094,13 @@ public void actionPerformed(ActionEvent evt) {
campaign.removeScenario(scenario.getBackingScenario());
}
break;
case RCLICK_COMMAND_RESET_DEPLOYMENT:
StratconScenario scenarioToReset = getSelectedScenario();

if (scenarioToReset != null) {
scenarioToReset.resetScenario(campaign);
}
break;
}

repaint();
Expand Down
31 changes: 27 additions & 4 deletions MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -1141,10 +1141,21 @@ protected Optional<JPopupMenu> createPopupMenu() {
}

if (StaticChecks.areAllForcesDeployed(forces)) {
menuItem = new JMenuItem("Undeploy Force (GM)");
menuItem = new JMenuItem("Undeploy Force");
menuItem.setActionCommand(TOEMouseAdapter.COMMAND_UNDEPLOY_FORCE + forceIds);
menuItem.addActionListener(this);
menuItem.setEnabled(gui.getCampaign().isGM() || !gui.getCampaign().getCampaignOptions().isUseStratCon());

boolean enable = true;
for (Force individualForce : forces) {
int scenarioId = individualForce.getScenarioId();
Scenario scenario = gui.getCampaign().getScenario(scenarioId);

if (scenario != null && scenario.getHasTrack()) {
enable = false;
break;
}
}
menuItem.setEnabled(enable);
popup.add(menuItem);
}

Expand Down Expand Up @@ -1642,10 +1653,22 @@ protected Optional<JPopupMenu> createPopupMenu() {
}

if (StaticChecks.areAllUnitsDeployed(units)) {
menuItem = new JMenuItem("Undeploy Unit (GM)");
menuItem = new JMenuItem("Undeploy Unit");
menuItem.setActionCommand(TOEMouseAdapter.COMMAND_UNDEPLOY_UNIT + unitIds);
menuItem.addActionListener(this);
menuItem.setEnabled(gui.getCampaign().isGM() || !gui.getCampaign().getCampaignOptions().isUseStratCon());

boolean enable = true;
for (Unit individualUnit : units) {
int scenarioId = individualUnit.getScenarioId();
Scenario scenario = gui.getCampaign().getScenario(scenarioId);

if (scenario != null && scenario.getHasTrack()) {
enable = false;
break;
}
}

menuItem.setEnabled(enable);
popup.add(menuItem);
}

Expand Down
14 changes: 12 additions & 2 deletions MekHQ/src/mekhq/gui/adapter/UnitTableMouseAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import mekhq.campaign.event.UnitChangedEvent;
import mekhq.campaign.finances.Money;
import mekhq.campaign.finances.enums.TransactionType;
import mekhq.campaign.mission.Scenario;
import mekhq.campaign.parts.Part;
import mekhq.campaign.parts.Refit;
import mekhq.campaign.parts.enums.PartQuality;
Expand Down Expand Up @@ -1008,10 +1009,19 @@ protected Optional<JPopupMenu> createPopupMenu() {
}

if (oneDeployed) {
menuItem = new JMenuItem("Undeploy Unit (GM)");
menuItem = new JMenuItem("Undeploy Unit");
menuItem.setActionCommand(COMMAND_UNDEPLOY);
menuItem.addActionListener(this);
menuItem.setEnabled(gui.getCampaign().isGM() || !gui.getCampaign().getCampaignOptions().isUseStratCon());

boolean enable = true;
int scenarioId = unit.getScenarioId();
Scenario scenario = gui.getCampaign().getScenario(scenarioId);

if (scenario != null && scenario.getHasTrack()) {
enable = false;
}

menuItem.setEnabled(enable);
menu.add(menuItem);
}

Expand Down

0 comments on commit d187832

Please sign in to comment.