From f9dcb04631c4ceec0ec210cba4f8228053b764b7 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 27 Jan 2025 10:23:40 -0600 Subject: [PATCH 1/3] Refactor mission role references for cleaner imports Replaced fully qualified `MissionRole` enum references with direct imports to simplify code and improve readability. Introduced a helper method to handle weight class bypass logic based on specific mission roles, ensuring better unit generation outcomes in constrained scenarios. --- .../mission/AtBDynamicScenarioFactory.java | 81 +++++++++++++------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java index caf1bdf6ef..c9f2a4f377 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java @@ -68,7 +68,7 @@ import static java.lang.Math.max; import static java.lang.Math.round; -import static megamek.client.ratgenerator.MissionRole.CIVILIAN; +import static megamek.client.ratgenerator.MissionRole.*; import static megamek.common.Compute.randomInt; import static megamek.common.UnitType.*; import static megamek.common.planetaryconditions.Wind.TORNADO_F4; @@ -581,9 +581,9 @@ public static int generateForce(AtBDynamicScenario scenario, AtBContract contrac if (allowsConvInfantry && (isTainted || isLowPressure || isLowGravity)) { Collection infantryRoles = new HashSet<>(); if (isLowGravity) { - infantryRoles.add(MissionRole.MARINE); + infantryRoles.add(MARINE); } else { - infantryRoles.add(MissionRole.XCT); + infantryRoles.add(XCT); } if (requiredRoles.containsKey(INFANTRY)) { requiredRoles.get(INFANTRY).addAll(infantryRoles); @@ -601,19 +601,19 @@ public static int generateForce(AtBDynamicScenario scenario, AtBContract contrac if (!requiredRoles.containsKey(MEK)) { requiredRoles.put(MEK, new HashSet<>()); } - requiredRoles.get(MEK).add((MissionRole.ARTILLERY)); + requiredRoles.get(MEK).add((ARTILLERY)); } if (artilleryCarriers == SPECIAL_UNIT_TYPE_ATB_MIX || artilleryCarriers == TANK) { if (!requiredRoles.containsKey(TANK)) { requiredRoles.put(TANK, new HashSet<>()); } - requiredRoles.get(TANK).add((MissionRole.ARTILLERY)); + requiredRoles.get(TANK).add((ARTILLERY)); } if (artilleryCarriers == INFANTRY) { if (!requiredRoles.containsKey(INFANTRY)) { requiredRoles.put(INFANTRY, new HashSet<>()); } - requiredRoles.get(INFANTRY).add((MissionRole.ARTILLERY)); + requiredRoles.get(INFANTRY).add((ARTILLERY)); } } @@ -1782,11 +1782,13 @@ public static Entity getEntity(String faction, params.setFaction(faction); params.setQuality(quality); params.setUnitType(unitType); - params.setWeightClass(weightClass); params.setYear(campaign.getGameYear()); + params.setMissionRoles(rolesByType); if (rolesByType != null && !rolesByType.isEmpty()) { - params.setMissionRoles(rolesByType); + params.setWeightClass(shouldBypassWeightClass(rolesByType) + ? UNIT_WEIGHT_UNSPECIFIED + : weightClass); } // Vehicles and infantry require some additional processing @@ -1805,6 +1807,33 @@ public static Entity getEntity(String faction, return createEntityWithCrew(faction, skill, campaign, unitData); } + /** + * Determines whether the weight class constraints should be bypassed based on the given mission roles. + *

+ * This method evaluates if the provided {@code rolesByType} contain any of the predefined mission roles + * that should bypass the weight class restrictions. The bypassed roles are selected because they use + * relatively small or exclusive unit pools, which improves the likelihood of successfully finding + * an appropriate unit. + *

+ * + * @param rolesByType a collection of mission roles to evaluate. + * @return {@code true} if any role in {@code rolesByType} matches one of the predefined bypassed roles. + */ + private static boolean shouldBypassWeightClass(Collection rolesByType) { + // These roles were picked as their pool is relatively small, or they are exclusive in nature. + // This ensures we have a greater chance of successfully pulling an appropriate unit. + List bypassedRoles = List.of(CIVILIAN, SUPPORT, ARTILLERY, MISSILE_ARTILLERY, + APC, SPECOPS, ENGINEER, MINESWEEPER, MINELAYER); + + for (MissionRole role : rolesByType) { + if (bypassedRoles.contains(role)) { + return true; + } + } + + return false; + } + /** * Randomly creates a ground vehicle, or VTOL if campaign options allows, with a * randomly @@ -1884,9 +1913,9 @@ public static Entity getInfantryEntity(UnitGeneratorParameters params, if (unitData == null) { // If XCT troops were requested but none were found, generate without the role - if (useTempXCT && params.getMissionRoles().contains(MissionRole.XCT)) { + if (useTempXCT && params.getMissionRoles().contains(XCT)) { noXCTParams = params.clone(); - noXCTParams.getMissionRoles().remove(MissionRole.XCT); + noXCTParams.getMissionRoles().remove(XCT); unitData = campaign.getUnitGenerator().generate(noXCTParams); temporaryXCT = true; } @@ -1996,13 +2025,13 @@ public static List fillTransports(AtBScenario scenario, transportedRoles.put(INFANTRY, requiredRoles.containsKey(INFANTRY) ? new ArrayList<>(requiredRoles.get(INFANTRY)) : new ArrayList<>()); - transportedRoles.get(INFANTRY).remove((MissionRole.ARTILLERY)); + transportedRoles.get(INFANTRY).remove((ARTILLERY)); transportedRoles.put(BATTLE_ARMOR, requiredRoles.containsKey(BATTLE_ARMOR) ? new ArrayList<>(requiredRoles.get(BATTLE_ARMOR)) : new ArrayList<>()); - transportedRoles.get(BATTLE_ARMOR).remove((MissionRole.ARTILLERY)); + transportedRoles.get(BATTLE_ARMOR).remove((ARTILLERY)); } List transportedUnits = new ArrayList<>(); @@ -2099,9 +2128,9 @@ private static List fillTransport(AtBScenario scenario, if (transportedUnit == null && allowInfantry) { newParams.setMissionRoles(requiredRoles.getOrDefault(INFANTRY, new HashSet<>())); if (transport.getUnitType() == VTOL - && !newParams.getMissionRoles().contains(MissionRole.XCT)) { + && !newParams.getMissionRoles().contains(XCT)) { UnitGeneratorParameters paratrooperParams = newParams.clone(); - paratrooperParams.addMissionRole(MissionRole.PARATROOPER); + paratrooperParams.addMissionRole(PARATROOPER); transportedUnit = generateTransportedInfantryUnit(paratrooperParams, bayCapacity, skill, true, campaign); } else { @@ -2179,7 +2208,7 @@ private static Entity generateTransportedInfantryUnit(UnitGeneratorParameters pa // include other types if (bayCapacity <= IUnitGenerator.FOOT_PLATOON_INFANTRY_WEIGHT) { - if (newParams.getMissionRoles().contains(MissionRole.PARATROOPER)) { + if (newParams.getMissionRoles().contains(PARATROOPER)) { newParams.setMovementModes(IUnitGenerator.ALL_INFANTRY_MODES); } else { newParams.getMovementModes().add(EntityMovementMode.INF_LEG); @@ -2190,9 +2219,9 @@ private static Entity generateTransportedInfantryUnit(UnitGeneratorParameters pa if (unitData == null) { // If XCT troops were requested but none were found, generate without the role - if (useTempXCT && newParams.getMissionRoles().contains(MissionRole.XCT)) { + if (useTempXCT && newParams.getMissionRoles().contains(XCT)) { noXCTParams = newParams.clone(); - noXCTParams.getMissionRoles().remove(MissionRole.XCT); + noXCTParams.getMissionRoles().remove(XCT); unitData = campaign.getUnitGenerator().generate(noXCTParams); temporaryXCT = true; } @@ -2221,9 +2250,9 @@ private static Entity generateTransportedInfantryUnit(UnitGeneratorParameters pa if (unitData == null) { // If XCT troops were requested but none were found, generate without the role - if (useTempXCT && newParams.getMissionRoles().contains(MissionRole.XCT)) { + if (useTempXCT && newParams.getMissionRoles().contains(XCT)) { noXCTParams = newParams.clone(); - noXCTParams.getMissionRoles().remove(MissionRole.XCT); + noXCTParams.getMissionRoles().remove(XCT); unitData = campaign.getUnitGenerator().generate(noXCTParams); temporaryXCT = true; } @@ -2283,7 +2312,7 @@ private static Entity generateTransportedBAUnit(UnitGeneratorParameters params, if (bayCapacity != IUnitGenerator.NO_WEIGHT_LIMIT) { newParams.setFilter(inf -> inf.getTons() <= bayCapacity); } else { - newParams.addMissionRole(MissionRole.MECHANIZED_BA); + newParams.addMissionRole(MECHANIZED_BA); } MekSummary unitData = campaign.getUnitGenerator().generate(newParams); @@ -2292,7 +2321,7 @@ private static Entity generateTransportedBAUnit(UnitGeneratorParameters params, if (unitData == null) { if (bayCapacity != IUnitGenerator.NO_WEIGHT_LIMIT && retryAsMechanized) { newParams.setFilter(null); - newParams.addMissionRole((MissionRole.MECHANIZED_BA)); + newParams.addMissionRole((MECHANIZED_BA)); unitData = campaign.getUnitGenerator().generate(newParams); } if (unitData == null) { @@ -2371,7 +2400,7 @@ public static List generateBAForNova(AtBScenario scenario, List params.setFaction(factionCode); params.setQuality(quality); params.setYear(campaign.getGameYear()); - params.addMissionRole(MissionRole.MECHANIZED_BA); + params.addMissionRole(MECHANIZED_BA); params.setWeightClass(UNIT_WEIGHT_UNSPECIFIED); Entity transportedUnit = generateTransportedBAUnit(params, IUnitGenerator.NO_WEIGHT_LIMIT, skill, false, @@ -2914,19 +2943,19 @@ private static List generateClanUnitTypes(int unitCount, if (requiredRoles != null && !requiredRoles.isEmpty()) { for (int curType : requiredRoles.keySet()) { - if (requiredRoles.get(curType).contains(MissionRole.RECON)) { + if (requiredRoles.get(curType).contains(RECON)) { if (curType == MEK || curType == PROTOMEK) { weights = adjustForMaxWeight(weights, EntityWeightClass.WEIGHT_MEDIUM); } } - if (requiredRoles.get(curType).contains(MissionRole.APC)) { + if (requiredRoles.get(curType).contains(APC)) { if (curType == TANK || curType == VTOL) { weights = adjustForMaxWeight(weights, EntityWeightClass.WEIGHT_MEDIUM); } } - if (requiredRoles.get(curType).contains(MissionRole.CAVALRY)) { + if (requiredRoles.get(curType).contains(CAVALRY)) { if (curType == MEK) { weights = adjustForMaxWeight(weights, EntityWeightClass.WEIGHT_HEAVY); } else if (curType == TANK || curType == PROTOMEK) { @@ -2934,7 +2963,7 @@ private static List generateClanUnitTypes(int unitCount, } } - if (requiredRoles.get(curType).contains(MissionRole.RAIDER)) { + if (requiredRoles.get(curType).contains(RAIDER)) { if (curType == MEK || curType == PROTOMEK) { weights = adjustForMaxWeight(weights, EntityWeightClass.WEIGHT_HEAVY); } From 77392c983f4fbc03d62e7ae283faec063d85451b Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 27 Jan 2025 10:29:54 -0600 Subject: [PATCH 2/3] Update copyright year to 2025 Updated the copyright notice in AtBDynamicScenarioFactory.java to reflect the current year. Ensured proper attribution for ongoing development and maintenance. --- MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java index c9f2a4f377..55acdfab05 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2024 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2019-2025 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * From ea091eb8e4523c88910be4fe0e080a5dc9ffd6e6 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 27 Jan 2025 11:18:31 -0600 Subject: [PATCH 3/3] Added MIXED_ARTILLERY to the bypass list --- MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java index 55acdfab05..882a50e26f 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java @@ -1823,7 +1823,7 @@ private static boolean shouldBypassWeightClass(Collection rolesByTy // These roles were picked as their pool is relatively small, or they are exclusive in nature. // This ensures we have a greater chance of successfully pulling an appropriate unit. List bypassedRoles = List.of(CIVILIAN, SUPPORT, ARTILLERY, MISSILE_ARTILLERY, - APC, SPECOPS, ENGINEER, MINESWEEPER, MINELAYER); + MIXED_ARTILLERY, APC, SPECOPS, ENGINEER, MINESWEEPER, MINELAYER); for (MissionRole role : rolesByType) { if (bypassedRoles.contains(role)) {