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

fixes for multiple stratcon issues; objective display improvement #2756

Merged
merged 4 commits into from
Jul 21, 2021
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
3 changes: 0 additions & 3 deletions MekHQ/data/scenariomodifiers/EnemyArty.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@
<generationMethod>3</generationMethod>
<generationOrder>3</generationOrder>
<maxWeightClass>4</maxWeightClass>
<objectiveLinkedForces>
<objectiveLinkedForce>Primary Opfor</objectiveLinkedForce>
</objectiveLinkedForces>
<retreatThreshold>50</retreatThreshold>
<startingAltitude>0</startingAltitude>
<syncDeploymentType>None</syncDeploymentType>
Expand Down
129 changes: 67 additions & 62 deletions MekHQ/data/scenariotemplates/Pursuit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<name>Pursuit</name>
<shortBriefing>Escape superior pursuing enemy force.</shortBriefing>
<detailedBriefing>Reach the far edge of the map or destroy 50% of the pursuing force.</detailedBriefing>
<isHostileFacility>false</isHostileFacility>
<isAlliedFacility>false</isAlliedFacility>
<mapParameters>
<allowedTerrainTypes/>
<allowRotation>true</allowRotation>
Expand All @@ -13,6 +15,66 @@
<useStandardAtBSizing>false</useStandardAtBSizing>
<widthScalingIncrement>1</widthScalingIncrement>
</mapParameters>
<scenarioObjectives>
<scenarioObjective>
<associatedForceNames>
<associatedForceName>Player</associatedForceName>
</associatedForceNames>
<associatedUnitIDs/>
<successEffects>
<successEffect>
<effectType>ScenarioVictory</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>2</howMuch>
</successEffect>
</successEffects>
<failureEffects>
<failureEffect>
<effectType>ScenarioDefeat</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>1</howMuch>
</failureEffect>
</failureEffects>
<additionalDetails>
<additionalDetail>Crippled units do not count towards this objective.</additionalDetail>
</additionalDetails>
<description>Reach the far edge of the map with at least 50% of the following force(s) and unit(s):</description>
<destinationEdge>NONE</destinationEdge>
<objectiveCriterion>ReachMapEdge</objectiveCriterion>
<percentage>50</percentage>
<timeLimit>0</timeLimit>
<timeLimitAtMost>true</timeLimitAtMost>
<timeLimitType>None</timeLimitType>
</scenarioObjective>
<scenarioObjective>
<associatedForceNames>
<associatedForceName>Primary Opfor</associatedForceName>
</associatedForceNames>
<associatedUnitIDs/>
<successEffects>
<successEffect>
<effectType>ScenarioVictory</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>2</howMuch>
</successEffect>
</successEffects>
<failureEffects>
<failureEffect>
<effectType>ScenarioDefeat</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>1</howMuch>
</failureEffect>
</failureEffects>
<additionalDetails/>
<description>Destroy or rout 50% of the following force(s) and unit(s):</description>
<destinationEdge>NONE</destinationEdge>
<objectiveCriterion>ForceWithdraw</objectiveCriterion>
<percentage>50</percentage>
<timeLimit>0</timeLimit>
<timeLimitAtMost>true</timeLimitAtMost>
<timeLimitType>None</timeLimitType>
</scenarioObjective>
</scenarioObjectives>
<scenarioForces>
<entry>
<key>Player</key>
Expand All @@ -29,7 +91,7 @@
<deploymentZones>
<deploymentZone>11</deploymentZone>
</deploymentZones>
<destinationZone>5</destinationZone>
<destinationZone>6</destinationZone>
<fixedUnitCount>0</fixedUnitCount>
<forceAlignment>0</forceAlignment>
<forceMultiplier>1.0</forceMultiplier>
Expand All @@ -38,6 +100,7 @@
<generationOrder>1</generationOrder>
<maxWeightClass>4</maxWeightClass>
<minWeightClass>0</minWeightClass>
<objectiveLinkedForces/>
<retreatThreshold>50</retreatThreshold>
<startingAltitude>0</startingAltitude>
<syncDeploymentType>None</syncDeploymentType>
Expand All @@ -59,7 +122,7 @@
<deploymentZones>
<deploymentZone>11</deploymentZone>
</deploymentZones>
<destinationZone>6</destinationZone>
<destinationZone>5</destinationZone>
<fixedUnitCount>0</fixedUnitCount>
<forceAlignment>2</forceAlignment>
<forceMultiplier>2.0</forceMultiplier>
Expand All @@ -68,6 +131,7 @@
<generationOrder>5</generationOrder>
<maxWeightClass>4</maxWeightClass>
<minWeightClass>1</minWeightClass>
<objectiveLinkedForces/>
<retreatThreshold>50</retreatThreshold>
<startingAltitude>0</startingAltitude>
<syncDeploymentType>None</syncDeploymentType>
Expand Down Expand Up @@ -96,6 +160,7 @@
<generationOrder>1</generationOrder>
<maxWeightClass>4</maxWeightClass>
<minWeightClass>1</minWeightClass>
<objectiveLinkedForces/>
<retreatThreshold>50</retreatThreshold>
<startingAltitude>0</startingAltitude>
<syncDeploymentType>OppositeEdge</syncDeploymentType>
Expand All @@ -104,64 +169,4 @@
</value>
</entry>
</scenarioForces>
<scenarioObjectives>
<scenarioObjective>
<associatedForceNames>
<associatedForceName>Player</associatedForceName>
</associatedForceNames>
<associatedUnitIDs/>
<successEffects>
<successEffect>
<effectType>ScenarioVictory</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>2</howMuch>
</successEffect>
</successEffects>
<failureEffects>
<failureEffect>
<effectType>ScenarioDefeat</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>1</howMuch>
</failureEffect>
</failureEffects>
<additionalDetails>
<additionalDetail>Crippled units do not count towards this objective.</additionalDetail>
</additionalDetails>
<description>Reach the far edge of the map with at least 50% of the following force(s) and unit(s):</description>
<destinationEdge>NONE</destinationEdge>
<objectiveCriterion>ReachMapEdge</objectiveCriterion>
<percentage>50</percentage>
<timeLimit>0</timeLimit>
<timeLimitAtMost>true</timeLimitAtMost>
<timeLimitType>None</timeLimitType>
</scenarioObjective>
<scenarioObjective>
<associatedForceNames>
<associatedForceName>Primary Opfor</associatedForceName>
</associatedForceNames>
<associatedUnitIDs/>
<successEffects>
<successEffect>
<effectType>ScenarioVictory</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>2</howMuch>
</successEffect>
</successEffects>
<failureEffects>
<failureEffect>
<effectType>ScenarioDefeat</effectType>
<effectScaling>Fixed</effectScaling>
<howMuch>1</howMuch>
</failureEffect>
</failureEffects>
<additionalDetails/>
<description>Destroy or rout 50% of the following force(s) and unit(s):</description>
<destinationEdge>NONE</destinationEdge>
<objectiveCriterion>ForceWithdraw</objectiveCriterion>
<percentage>50</percentage>
<timeLimit>0</timeLimit>
<timeLimitAtMost>true</timeLimitAtMost>
<timeLimitType>None</timeLimitType>
</scenarioObjective>
</scenarioObjectives>
</ScenarioTemplate>
16 changes: 14 additions & 2 deletions MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1422,9 +1422,14 @@ private static void updateStrategicObjectives(boolean victory, StratconScenario

// first, we check if this scenario is associated with any specific scenario objectives
StratconStrategicObjective specificObjective = track.getObjectivesByCoords().get(scenario.getCoords());
if (victory && (specificObjective != null) &&
if ((specificObjective != null) &&
(specificObjective.getObjectiveType() == StrategicObjectiveType.SpecificScenarioVictory)) {
specificObjective.incrementCurrentObjectiveCount();

if (victory) {
specificObjective.incrementCurrentObjectiveCount();
} else {
specificObjective.setCurrentObjectiveCount(StratconStrategicObjective.OBJECTIVE_FAILED);
}
}

// "any scenario victory" is not linked to any specific coordinates, so we have to
Expand Down Expand Up @@ -1542,6 +1547,12 @@ public static boolean processIgnoredScenario(StratconScenario scenario, Stratcon
if (closestAlliedFacilityCoords != null) {
StratconCoords newCoords = scenario.getCoords()
.translate(scenario.getCoords().direction(closestAlliedFacilityCoords));

boolean objectiveMoved = track.moveObjective(scenario.getCoords(), newCoords);
if (!objectiveMoved) {
track.failObjective(scenario.getCoords());
}

scenario.setCoords(newCoords);

int daysForward = Math.max(1, track.getDeploymentTime());
Expand All @@ -1563,6 +1574,7 @@ public static boolean processIgnoredScenario(StratconScenario scenario, Stratcon
scenario.setCurrentState(ScenarioState.UNRESOLVED);
return false;
} else {
track.failObjective(scenario.getCoords());
// TODO: if there's no allied facilities here, add its forces to track
// reinforcement pool
return true;
Expand Down
24 changes: 24 additions & 0 deletions MekHQ/src/mekhq/campaign/stratcon/StratconStrategicObjective.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* and also handles some small amount of "business logic"
*/
public class StratconStrategicObjective {
public static final int OBJECTIVE_FAILED = -1;

private StratconCoords objectiveCoords;
private StrategicObjectiveType objectiveType;
Expand Down Expand Up @@ -69,6 +70,29 @@ public void setDesiredObjectiveCount(int desiredObjectiveCount) {
this.desiredObjectiveCount = desiredObjectiveCount;
}

public boolean isObjectiveFailed(StratconTrackState trackState) {
switch (getObjectiveType()) {
case AnyScenarioVictory:
case SpecificScenarioVictory:
// you can fail this if the scenario goes away somehow
return getCurrentObjectiveCount() == OBJECTIVE_FAILED;
case AlliedFacilityControl:
// you can fail this by having the facility destroyed
StratconFacility alliedFacility = trackState.getFacility(getObjectiveCoords());
return alliedFacility == null;
case HostileFacilityControl:
// you can fail this by having the facility destroyed
StratconFacility hostileFacility = trackState.getFacility(getObjectiveCoords());
return hostileFacility == null;
case FacilityDestruction:
// you can't really permanently fail this
return false;
default:
// we shouldn't be here, but just in case
return false;
}
}

/**
* Given the track that this objective is on, is it complete?
*/
Expand Down
28 changes: 28 additions & 0 deletions MekHQ/src/mekhq/campaign/stratcon/StratconTrackState.java
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,34 @@ public Map<StratconCoords, StratconStrategicObjective> getObjectivesByCoords() {
return specificStrategicObjectives;
}

/**
* Moves a strategic objectives from the source to the destination coordinates.
* @return True if the operation succeeded, false if it failed
*/
public boolean moveObjective(StratconCoords source, StratconCoords destination) {
// safety: don't move it if it's not there; logic prevents two objectives in the same coords
if (getObjectivesByCoords().containsKey(source) &&
!getObjectivesByCoords().containsKey(destination)) {
StratconStrategicObjective objective = getObjectivesByCoords().get(source);
// gotta get the cache
getObjectivesByCoords().remove(source);
getObjectivesByCoords().put(destination, objective);
objective.setObjectiveCoords(destination);
return true;
} else {
return false;
}
}

/**
* Convenience method to fail an objective at the given coordinates.
*/
public void failObjective(StratconCoords coords) {
if (getObjectivesByCoords().containsKey(coords)) {
getObjectivesByCoords().get(coords).setCurrentObjectiveCount(StratconStrategicObjective.OBJECTIVE_FAILED);
}
}

/**
* Convenience method - returns true if the force with the given ID is currently deployed to this track
*/
Expand Down
28 changes: 21 additions & 7 deletions MekHQ/src/mekhq/gui/StratconTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
public class StratconTab extends CampaignGuiTab {
private static final long serialVersionUID = 8179754409939346465L;

private static final String OBJECTIVE_FAILED = "x";
private static final String OBJECTIVE_COMPLETED = "&#10003;";
private static final String OBJECTIVE_IN_PROGRESS = "o";

private StratconPanel stratconPanel;
private JPanel infoPanel;
private JComboBox<TrackDropdownItem> cboCurrentTrack;
Expand Down Expand Up @@ -304,15 +308,21 @@ private String buildStrategicObjectiveText(StratconCampaignState campaignState)
boolean coordsRevealed = track.getRevealedCoords().contains(objective.getObjectiveCoords());
boolean displayCoordinateData = objective.getObjectiveCoords() != null;
boolean objectiveCompleted = objective.isObjectiveCompleted(track);
boolean objectiveFailed = objective.isObjectiveFailed(track);

// special case: allied facilities can get lost at any point in time
if ((objective.getObjectiveType() == StrategicObjectiveType.AlliedFacilityControl) &&
!campaignState.allowEarlyVictory()) {
sb.append("<span>");
sb.append("<span color='orange'>").append(OBJECTIVE_IN_PROGRESS);
} else if (objectiveCompleted) {
sb.append("<span color='green'>");
sb.append("<span color='green'>").append(OBJECTIVE_COMPLETED);
} else if (objectiveFailed) {
sb.append("<span color='red'>").append(OBJECTIVE_FAILED);
} else {
sb.append("<span color='red'>");
sb.append("<span color='orange'>").append(OBJECTIVE_IN_PROGRESS);
}

sb.append(" ");

if (!coordsRevealed && displayCoordinateData) {
sb.append("Locate and ");
Expand Down Expand Up @@ -355,13 +365,17 @@ private String buildStrategicObjectiveText(StratconCampaignState campaignState)

// special case text reminding player to complete required scenarios
if (!campaignState.getContract().getCommandRights().isIndependent()) {
if (campaignState.getVictoryPoints() > 0) {
sb.append("<span color='green'>");
boolean contractIsActive = campaignState.getContract().isActiveOn(getCampaignGui().getCampaign().getLocalDate());

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

sb.append("Maintain victory point count above 0 by completing required scenarios")
sb.append(" Maintain victory point count above 0 by completing required scenarios")
.append("</span><br/>");
}

Expand Down
5 changes: 3 additions & 2 deletions MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -917,9 +917,10 @@ protected Optional<JPopupMenu> createPopupMenu() {
for (final Mission mission : gui.getCampaign().getActiveMissions()) {
missionMenu = new JMenu(mission.getName());
for (final Scenario scenario : mission.getCurrentScenarios()) {
if (gui.getCampaign().getCampaignOptions().getUseAtB()
if (scenario.isCloaked()
|| (gui.getCampaign().getCampaignOptions().getUseAtB()
&& (scenario instanceof AtBScenario)
&& !((AtBScenario) scenario).canDeployForces(forces, gui.getCampaign())) {
&& !((AtBScenario) scenario).canDeployForces(forces, gui.getCampaign()))) {
continue;
}
menuItem = new JMenuItem(scenario.getName());
Expand Down