Skip to content

Commit

Permalink
Updated PreSeeded Enemy Forces Spawn
Browse files Browse the repository at this point in the history
PreSeeded enemy force count is now based on enemy quality and faction.
  • Loading branch information
IllianiCBT committed Nov 21, 2024
1 parent bad4866 commit 8877ecb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
14 changes: 12 additions & 2 deletions MekHQ/src/mekhq/campaign/mission/enums/AtBContractType.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
*/
package mekhq.campaign.mission.enums;

import java.util.ResourceBundle;

import megamek.common.Compute;
import megamek.logging.MMLogger;
import mekhq.MekHQ;
Expand All @@ -28,6 +26,8 @@
import mekhq.campaign.mission.AtBScenario;
import mekhq.campaign.universe.enums.EraFlag;

import java.util.ResourceBundle;

public enum AtBContractType {
// TODO: Missing Camops Mission Types: ASSASSINATION, ESPIONAGE, MOLE_HUNTING, OBSERVATION_RAID,
// RETAINER, SABOTAGE, TERRORISM, HIGH_RISK
Expand Down Expand Up @@ -138,6 +138,16 @@ public boolean isGarrisonType() {
public boolean isRaidType() {
return isDiversionaryRaid() || isObjectiveRaid() || isReconRaid() || isExtractionRaid();
}

/**
* Checks if the given contract is offensive.
*
* @return {@code true} if the contract is of raid type, pirate hunting, or guerrilla warfare;
* {@code false} otherwise
*/
public boolean isOffensive() {
return isRaidType() || isPirateHunting() || isGuerrillaWarfare();
}
// endregion Boolean Comparison Methods

public int calculateLength(final boolean variable, final AtBContract contract) {
Expand Down
63 changes: 32 additions & 31 deletions MekHQ/src/mekhq/campaign/stratcon/StratconContractInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@

import static java.lang.Math.round;
import static megamek.common.Coords.ALL_DIRECTIONS;
import static mekhq.campaign.rating.IUnitRating.*;
import static mekhq.campaign.stratcon.StratconRulesManager.addHiddenExternalScenario;
import static mekhq.campaign.stratcon.StratconRulesManager.calculateScenarioOdds;

/**
* This class handles StratCon state initialization when a contract is signed.
Expand Down Expand Up @@ -195,9 +195,7 @@ public static void initializeCampaignState(AtBContract contract, Campaign campai

// Initialize non-objective scenarios
for (StratconTrackState track : campaignState.getTracks()) {
if (seedPreDeployedForces(contract, campaign, track)) {
break;
}
seedPreDeployedForces(contract, campaign, track);
}

// clean up objectives for integrated command:
Expand All @@ -216,48 +214,51 @@ public static void initializeCampaignState(AtBContract contract, Campaign campai

/**
* Seeds pre-deployed (hidden) forces in a {@link StratconTrackState}, taking into account
* contract type and intensity.
* contract type, enemy quality, and enemy faction.
*
* @param contract the current contract
* @param campaign the current campaign.
* @param track the relevant {@link StratconTrackState}
*
* @return a boolean where {@code true} means forces were not deployed due to being garrison
* type or pirate hunting and {@code false} implies forces have been deployed successfully.
*/
public static boolean seedPreDeployedForces(AtBContract contract, Campaign campaign, StratconTrackState track) {
public static void seedPreDeployedForces(AtBContract contract, Campaign campaign, StratconTrackState track) {
final int CLAN_CLUSTER = 27; // Stars
final int IS_BATTALION = 27; // Lances
final int COMSTAR_LEVEL_IV = 36; // Level IIs

double multiplier = switch (contract.getEnemyQuality()) {
case DRAGOON_F -> 0.25;
case DRAGOON_D -> 0.5;
case DRAGOON_C -> 0.75;
case DRAGOON_B -> 1;
case DRAGOON_A -> 1.5;
case DRAGOON_ASTAR -> 2;
default ->
throw new IllegalStateException(
"Unexpected value in mekhq/campaign/stratcon/StratconContractInitializer.java/seedPreDeployedForces: "
+ contract.getEnemyQuality());
};

AtBContractType contractType = contract.getContractType();

// If the contract is a garrison type, we don't want to generate what will appear to be
// a full-scale invasion on day one. Furthermore, Pirates do not have enough resources
// to deploy standing forces in this manner.
if (contractType.isGarrisonType() || contractType.isPirateHunting()) {
return true;
if (contractType.isPirateHunting() || contractType.isGarrisonType()) {
multiplier *= 0.5;
} else if (contractType.isOffensive()) {
multiplier *= 2;
}

// otherwise, seed each sector with hidden forces.
// the number of hidden forces is dependent on the type of contract.
final int OFFENSIVE_MULTIPLIER = 10;
final int DEFENSIVE_MULTIPLIER = 20;

int multiplier = DEFENSIVE_MULTIPLIER;
int elementCount = IS_BATTALION;

if (contractType.isGarrisonType() || contractType.isPirateHunting()) {
multiplier = (int) (DEFENSIVE_MULTIPLIER * 1.5);
} else if (contractType.isRaidType() || contractType.isGuerrillaWarfare()) {
multiplier = OFFENSIVE_MULTIPLIER;
} else if (contract.getContractType().isPlanetaryAssault()) {
multiplier = OFFENSIVE_MULTIPLIER / 2;
if (contract.getEnemy().isClan()) {
elementCount = CLAN_CLUSTER;
} else if (contract.getEnemy().isComStarOrWoB()) {
elementCount = COMSTAR_LEVEL_IV;
}

int preDeployedScenarios = track.getSize() / multiplier;
preDeployedScenarios = (int) round(preDeployedScenarios
* ((double) calculateScenarioOdds(track, contract, false) / 100));
elementCount = (int) round(elementCount * multiplier);

for (int i = 0; i < preDeployedScenarios; i++) {
for (int i = 0; i < elementCount; i++) {
addHiddenExternalScenario(campaign, contract, track, null, false);
}
return false;
}

/**
Expand Down

0 comments on commit 8877ecb

Please sign in to comment.