From 33ce1ac518ef35b013f4096852e179c10e9c5834 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 25 Nov 2024 14:05:15 -0600 Subject: [PATCH 1/7] Refactor `Lance` to `StrategicFormation`. Updated all references from `Lance` to `StrategicFormation` in multiple classes for clarity and better alignment with game terminology. This includes method names, variables, and comments to reflect the changes more accurately. --- MekHQ/src/mekhq/AtBGameThread.java | 54 ++-- MekHQ/src/mekhq/campaign/Campaign.java | 36 +-- MekHQ/src/mekhq/campaign/force/Force.java | 45 +++ .../{Lance.java => StrategicFormation.java} | 300 ++++++++++-------- .../mekhq/campaign/io/CampaignXmlParser.java | 8 +- .../campaign/mission/AtBDynamicScenario.java | 10 +- .../mekhq/campaign/mission/AtBScenario.java | 75 ++--- .../mission/CommonObjectiveFactory.java | 10 +- .../mission/atb/AtBScenarioFactory.java | 89 +++--- .../scenario/BaseAttackBuiltInScenario.java | 19 +- .../scenario/BreakthroughBuiltInScenario.java | 13 +- .../atb/scenario/ChaseBuiltInScenario.java | 25 +- .../scenario/ExtractionBuiltInScenario.java | 15 +- .../scenario/HideAndSeekBuiltInScenario.java | 7 +- .../scenario/HoldTheLineBuiltInScenario.java | 6 +- .../atb/scenario/ProbeBuiltInScenario.java | 15 +- .../scenario/ReconRaidBuiltInScenario.java | 19 +- .../atb/scenario/StandUpBuiltInScenario.java | 6 +- .../personnel/autoAwards/MiscAwards.java | 2 +- .../stratcon/StratconRulesManager.java | 14 +- MekHQ/src/mekhq/gui/BriefingTab.java | 6 +- .../stratcon/ScenarioWizardLanceRenderer.java | 4 +- .../mekhq/gui/view/AtBScenarioViewPanel.java | 24 +- .../mekhq/gui/view/LanceAssignmentView.java | 92 +++--- 24 files changed, 453 insertions(+), 441 deletions(-) rename MekHQ/src/mekhq/campaign/force/{Lance.java => StrategicFormation.java} (59%) diff --git a/MekHQ/src/mekhq/AtBGameThread.java b/MekHQ/src/mekhq/AtBGameThread.java index c677ff356d..b99e7e36f4 100644 --- a/MekHQ/src/mekhq/AtBGameThread.java +++ b/MekHQ/src/mekhq/AtBGameThread.java @@ -18,22 +18,6 @@ */ package mekhq; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - -import javax.swing.JOptionPane; - import io.sentry.Sentry; import megamek.client.AbstractClient; import megamek.client.Client; @@ -41,24 +25,22 @@ import megamek.client.bot.princess.Princess; import megamek.client.generator.RandomCallsignGenerator; import megamek.client.ui.swing.ClientGUI; -import megamek.common.Entity; -import megamek.common.IAero; -import megamek.common.Infantry; -import megamek.common.MapSettings; -import megamek.common.Minefield; -import megamek.common.UnitType; +import megamek.common.*; import megamek.common.planetaryconditions.PlanetaryConditions; import megamek.logging.MMLogger; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBDynamicScenario; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.BotForce; -import mekhq.campaign.mission.Scenario; +import mekhq.campaign.force.StrategicFormation; +import mekhq.campaign.mission.*; import mekhq.campaign.personnel.Person; import mekhq.campaign.unit.Unit; +import javax.swing.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.*; + /** * Enhanced version of GameThread which imports settings and non-player units * into the MM game @@ -277,8 +259,8 @@ public void run() { // Set scenario type-specific delay deploymentRound = Math.max(entity.getDeployRound(), scenario.getDeploymentDelay() - speed); // Lances deployed in scout roles always deploy units in 6-walking speed turns - if (scenario.getLanceRole().isScouting() && (scenario.getLance(campaign) != null) - && (scenario.getLance(campaign).getForceId() == scenario.getLanceForceId()) + if (scenario.getLanceRole().isScouting() && (scenario.getStrategicFormation(campaign) != null) + && (scenario.getStrategicFormation(campaign).getForceId() == scenario.getStrategicFormationId()) && !useDropship) { deploymentRound = Math.max(deploymentRound, 6 - speed); } @@ -346,7 +328,7 @@ public void run() { } deploymentRound = Math.max(entity.getDeployRound(), scenario.getDeploymentDelay() - speed); if (!useDropship && scenario.getLanceRole().isScouting() - && (scenario.getLance(campaign).getForceId() == scenario.getLanceForceId())) { + && (scenario.getStrategicFormation(campaign).getForceId() == scenario.getStrategicFormationId())) { deploymentRound = Math.max(deploymentRound, 6 - speed); } } @@ -537,12 +519,12 @@ protected List setupBotEntities(BotClient botClient, BotForce botForce, int lanceSize; if (botForce.getTeam() == 2) { - lanceSize = Lance.getStdLanceSize(contract.getEnemy()); + lanceSize = StrategicFormation.getStdLanceSize(contract.getEnemy()); } else { - lanceSize = Lance.getStdLanceSize(contract.getEmployerFaction()); + lanceSize = StrategicFormation.getStdLanceSize(contract.getEmployerFaction()); } - Comparator comp = Comparator.comparing(((Entity e) -> e.getEntityMajorTypeName(e.getEntityType()))); + Comparator comp = Comparator.comparing(((Entity e) -> Entity.getEntityMajorTypeName(e.getEntityType()))); comp = comp.thenComparing(((Entity e) -> e.getRunMP()), Comparator.reverseOrder()); comp = comp.thenComparing(((Entity e) -> e.getRole().toString())); entitiesSorted.sort(comp); @@ -553,13 +535,13 @@ protected List setupBotEntities(BotClient botClient, BotForce botForce, } if ((i != 0) - && !lastType.equals(entity.getEntityMajorTypeName(entity.getEntityType()))) { + && !lastType.equals(Entity.getEntityMajorTypeName(entity.getEntityType()))) { forceIdLance++; lanceName = RCG.generate(); i = forceIdLance * lanceSize; } - lastType = entity.getEntityMajorTypeName(entity.getEntityType()); + lastType = Entity.getEntityMajorTypeName(entity.getEntityType()); entity.setOwner(botClient.getLocalPlayer()); String fName = String.format(forceName, lanceName, forceIdLance); entity.setForceString(fName); diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index f08daaaa43..c1faced120 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -51,7 +51,7 @@ import mekhq.campaign.finances.*; import mekhq.campaign.finances.enums.TransactionType; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.icons.StandardForceIcon; import mekhq.campaign.icons.UnitIcon; import mekhq.campaign.log.HistoricalLogEntry; @@ -199,7 +199,7 @@ public class Campaign implements ITechManager { // hierarchically structured Force object to define TO&E private Force forces; - private final Hashtable lances; // AtB + private final Hashtable lances; // AtB private Faction faction; private int techFactionCode; @@ -448,15 +448,15 @@ public List getAllForces() { return new ArrayList<>(forceIds.values()); } - public void importLance(Lance l) { + public void importLance(StrategicFormation l) { lances.put(l.getForceId(), l); } - public Hashtable getLances() { + public Hashtable getStrategicFormations() { return lances; } - public ArrayList getLanceList() { + public ArrayList getStrategicFormationList() { return lances.values().stream() .filter(l -> forceIds.containsKey(l.getForceId())) .collect(Collectors.toCollection(ArrayList::new)); @@ -905,7 +905,7 @@ public void addForce(Force force, Force superForce) { if (campaignOptions.isUseAtB() && !force.getUnits().isEmpty()) { if (null == lances.get(id)) { - lances.put(id, new Lance(force.getId(), this)); + lances.put(id, new StrategicFormation(force.getId(), this)); } } @@ -1007,7 +1007,7 @@ public void addUnitToForce(@Nullable Unit u, int id) { } if ((null == lances.get(id)) && (null != force)) { - lances.put(id, new Lance(force.getId(), this)); + lances.put(id, new StrategicFormation(force.getId(), this)); } } } @@ -1018,7 +1018,7 @@ public void addUnitToForce(@Nullable Unit u, int id) { private void addAllLances(Force force) { if (!force.getUnits().isEmpty()) { - lances.put(force.getId(), new Lance(force.getId(), this)); + lances.put(force.getId(), new StrategicFormation(force.getId(), this)); } for (Force f : force.getSubForces()) { addAllLances(f); @@ -3618,7 +3618,7 @@ public int getDeploymentDeficit(AtBContract contract) { int role = -Math.max(1, contract.getRequiredLances() / 2); final AtBLanceRole requiredLanceRole = contract.getContractType().getRequiredLanceRole(); - for (Lance l : lances.values()) { + for (StrategicFormation l : lances.values()) { if (!l.getRole().isUnassigned() && (l.getMissionId() == contract.getId())) { total++; if (l.getRole() == requiredLanceRole) { @@ -3717,7 +3717,7 @@ && getLocation().getJumpPath().getLastSystem().getId().equals(contract.getSystem // If there is a standard battle set for today, deploy the lance. for (final AtBScenario s : contract.getCurrentAtBScenarios()) { if ((s.getDate() != null) && s.getDate().equals(getLocalDate())) { - int forceId = s.getLanceForceId(); + int forceId = s.getStrategicFormationId(); if ((lances.get(forceId) != null) && !forceIds.get(forceId).isDeployed()) { // If any unit in the force is under repair, don't deploy the force // Merely removing the unit from deployment would break with user expectation @@ -3776,11 +3776,11 @@ private void processNewDayATB() { if (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY) { processShipSearch(); - // Training Experience - Award to eligible training lances on active contracts - getLances().values().stream() - .filter(lance -> lance.getRole().isTraining() - && (lance.getContract(this) != null) && lance.isEligible(this) - && lance.getContract(this).isActiveOn(getLocalDate(), true)) + // Training Experience - Award to eligible training Strategic Formations on active contracts + getStrategicFormations().values().stream() + .filter(strategicFormation -> strategicFormation.getRole().isTraining() + && (strategicFormation.getContract(this) != null) && strategicFormation.isEligible(this) + && strategicFormation.getContract(this).isActiveOn(getLocalDate(), true)) .forEach(this::awardTrainingXP); } @@ -4841,9 +4841,9 @@ public void removePerson(final @Nullable Person person, final boolean log) { * commanding officer and * the minimum experience level of the unit's members. * - * @param l The {@link Lance} to calculate XP to award for training. + * @param l The {@link StrategicFormation} to calculate XP to award for training. */ - private void awardTrainingXP(final Lance l) { + private void awardTrainingXP(final StrategicFormation l) { for (UUID trainerId : forceIds.get(l.getForceId()).getAllUnits(true)) { Unit trainerUnit = getHangar().getUnit(trainerId); @@ -5597,7 +5597,7 @@ public void writeToXML(final PrintWriter pw) { if (!lances.isEmpty()) { MHQXMLUtility.writeSimpleXMLOpenTag(pw, indent++, "lances"); - for (Lance l : lances.values()) { + for (StrategicFormation l : lances.values()) { if (forceIds.containsKey(l.getForceId())) { l.writeToXML(pw, indent); } diff --git a/MekHQ/src/mekhq/campaign/force/Force.java b/MekHQ/src/mekhq/campaign/force/Force.java index ce602f978f..8008ab8914 100644 --- a/MekHQ/src/mekhq/campaign/force/Force.java +++ b/MekHQ/src/mekhq/campaign/force/Force.java @@ -221,6 +221,28 @@ public boolean isDeployed() { return parentForce; } + /** + * This method generates a list of all parent forces for the current force object in the + * hierarchy. It repeatedly fetches the parent force of the current force and adds it to a list + * until no more parent forces can be found (i.e., until the top of the force hierarchy is reached). + * + * @return A list of {@link Force} objects representing all the parent forces of the current + * force object in the hierarchy. The list will be empty if there are no parent forces. + */ + public List getAllParents() { + List parentForces = new ArrayList<>(); + + Force parentForce = getParentForce(); + + while (parentForce.getParentForce() != null) { + parentForces.add(parentForce.getParentForce()); + + parentForce = parentForce.getParentForce(); + } + + return parentForces; + } + public void setParentForce(final @Nullable Force parent) { this.parentForce = parent; } @@ -229,6 +251,29 @@ public Vector getSubForces() { return subForces; } + /** + * Returns a list of all of this forces' descendant forces. + * This includes direct child forces and their descendents recursively. + *

+ * This method works by first adding all direct child forces to the list, and + * then recursively adding their descendants by calling this method on each child + * force. + * + * @return A list of {@link Force} objects representing all descendant forces. + * If there are no descendant forces, this method will return an empty list. + */ + public List getAllSubForces() { + List allSubForces = new ArrayList<>(); + + for (Force subForce : subForces) { + allSubForces.add(subForce); + + allSubForces.addAll(subForce.getAllSubForces()); + } + + return allSubForces; + } + public boolean isAncestorOf(Force otherForce) { Force pForce = otherForce.getParentForce(); while (pForce != null) { diff --git a/MekHQ/src/mekhq/campaign/force/Lance.java b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java similarity index 59% rename from MekHQ/src/mekhq/campaign/force/Lance.java rename to MekHQ/src/mekhq/campaign/force/StrategicFormation.java index c22758c257..3b2c485f47 100644 --- a/MekHQ/src/mekhq/campaign/force/Lance.java +++ b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java @@ -39,19 +39,20 @@ import java.io.PrintWriter; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** - * Used by Against the Bot to track additional information about each force - * on the TO&E that has at least one unit assigned. Extra info includes - * whether - * the force counts as a lance (or star or level II) eligible for assignment - * to a mission role and what the assignment is on which contract. + * Used by Against the Bot & StratCon to track additional information about each force + * on the TO&E that has at least one unit assigned. Extra info includes whether + * the force counts as a Strategic Formation eligible for assignment to a scenario role + * and what the assignment is on which contract. * * @author Neoancient */ -public class Lance { - private static final MMLogger logger = MMLogger.create(Lance.class); +public class StrategicFormation { + private static final MMLogger logger = MMLogger.create(StrategicFormation.class); public static final int STR_IS = 4; public static final int STR_CLAN = 5; @@ -68,29 +69,39 @@ public class Lance { private AtBLanceRole role; private UUID commanderId; - public static int getStdLanceSize(Faction f) { - if (f.isClan()) { + /** + * Determines the standard size for a given faction. The size varies depending on whether the + * faction is a Clan, ComStar/WoB, or others (Inner Sphere). + * + * @param faction The {@link Faction} object for which the standard force size is to be calculated. + * @return The standard force size for the given faction. It returns {@code STR_CLAN} if the + * faction is a Clan, {@code STR_CS} if the faction is ComStar or WoB, and {@code STR_IS} otherwise. + */ + public static int getStdLanceSize(Faction faction) { + if (faction.isClan()) { return STR_CLAN; - } else if (f.getShortName().equals("CS") || f.getShortName().equals("WOB")) { + } else if (faction.isComStarOrWoB()) { return STR_CS; } else { return STR_IS; } } - public Lance() { - } + /** + * Default constructor + */ + public StrategicFormation() {} - public Lance(int fid, Campaign c) { - forceId = fid; + public StrategicFormation(int forceId, Campaign campaign) { + this.forceId = forceId; role = AtBLanceRole.UNASSIGNED; missionId = -1; - for (AtBContract contract : c.getActiveAtBContracts()) { + for (AtBContract contract : campaign.getActiveAtBContracts()) { missionId = ((contract.getParentContract() == null) ? contract : contract.getParentContract()).getId(); } - commanderId = findCommander(forceId, c); + commanderId = findCommander(this.forceId, campaign); } public int getForceId() { @@ -101,15 +112,15 @@ public int getMissionId() { return missionId; } - public AtBContract getContract(Campaign c) { - return (AtBContract) c.getMission(missionId); + public AtBContract getContract(Campaign campaign) { + return (AtBContract) campaign.getMission(missionId); } - public void setContract(AtBContract c) { - if (null == c) { + public void setContract(AtBContract atBContract) { + if (null == atBContract) { missionId = NO_MISSION; } else { - missionId = c.getId(); + missionId = atBContract.getId(); } } @@ -125,8 +136,8 @@ public UUID getCommanderId() { return commanderId; } - public Person getCommander(Campaign c) { - return c.getPerson(commanderId); + public Person getCommander(Campaign campaign) { + return campaign.getPerson(commanderId); } public void setCommander(UUID id) { @@ -137,22 +148,22 @@ public void setCommander(Person p) { commanderId = p.getId(); } - public void refreshCommander(Campaign c) { - commanderId = findCommander(forceId, c); + public void refreshCommander(Campaign campaign) { + commanderId = findCommander(forceId, campaign); } - public int getSize(Campaign c) { - if (c.getFaction().isClan()) { - return (int) Math.ceil(getEffectivePoints(c)); + public int getSize(Campaign campaign) { + if (campaign.getFaction().isClan()) { + return (int) Math.ceil(getEffectivePoints(campaign)); } - if (c.getForce(forceId) != null) { - return c.getForce(forceId).getUnits().size(); + if (campaign.getForce(forceId) != null) { + return campaign.getForce(forceId).getUnits().size(); } else { return 0; } } - public double getEffectivePoints(Campaign c) { + public double getEffectivePoints(Campaign campaign) { /* * Used to check against force size limits; for this purpose we * consider a 'Mek and a Point of BA to be a single Point so that @@ -163,8 +174,8 @@ public double getEffectivePoints(Campaign c) { double armor = 0.0; double infantry = 0.0; double other = 0.0; - for (UUID id : c.getForce(forceId).getUnits()) { - Unit unit = c.getUnit(id); + for (UUID id : campaign.getForce(forceId).getUnits()) { + Unit unit = campaign.getUnit(id); if (null != unit) { Entity entity = unit.getEntity(); if (null != entity) { @@ -185,7 +196,7 @@ public double getEffectivePoints(Campaign c) { return Math.max(armor, infantry) + other; } - public int getWeightClass(Campaign c) { + public int getWeightClass(Campaign campaign) { /* * Clan units only count half the weight of ASF and vehicles * (2/Point). IS units only count half the weight of vehicles @@ -193,9 +204,9 @@ public int getWeightClass(Campaign c) { * weight class and decreasing the enemy force against vehicle/combined * lances. */ - double weight = calculateTotalWeight(c, forceId); + double weight = calculateTotalWeight(campaign, forceId); - weight = weight * 4.0 / getStdLanceSize(c.getFaction()); + weight = weight * 4.0 / getStdLanceSize(campaign.getFaction()); if (weight < 40) { return EntityWeightClass.WEIGHT_ULTRA_LIGHT; } @@ -214,9 +225,10 @@ public int getWeightClass(Campaign c) { return EntityWeightClass.WEIGHT_SUPER_HEAVY; } - public boolean isEligible(Campaign c) { + public boolean isEligible(Campaign campaign) { // ensure the lance is marked as a combat force - final Force force = c.getForce(forceId); + final Force force = campaign.getForce(forceId); + if ((force == null) || !force.isCombatForce()) { return false; } @@ -225,25 +237,26 @@ public boolean isEligible(Campaign c) { * Check that the number of units and weight are within the limits * and that the force contains at least one ground unit. */ - if (c.getCampaignOptions().isLimitLanceNumUnits()) { - int size = getSize(c); - if (size < getStdLanceSize(c.getFaction()) - 1 || - size > getStdLanceSize(c.getFaction()) + 2) { + if (campaign.getCampaignOptions().isLimitLanceNumUnits()) { + int size = getSize(campaign); + if (size < getStdLanceSize(campaign.getFaction()) - 1 || + size > getStdLanceSize(campaign.getFaction()) + 2) { return false; } } - if (c.getCampaignOptions().isLimitLanceWeight() && - getWeightClass(c) > EntityWeightClass.WEIGHT_ASSAULT) { + if (campaign.getCampaignOptions().isLimitLanceWeight() && + getWeightClass(campaign) > EntityWeightClass.WEIGHT_ASSAULT) { return false; } boolean hasGround = false; for (UUID id : force.getUnits()) { - Unit unit = c.getUnit(id); - if (null != unit) { + Unit unit = campaign.getUnit(id); + if (unit != null) { Entity entity = unit.getEntity(); - if (null != entity) { + + if (entity != null) { if (entity.getUnitType() >= UnitType.JUMPSHIP) { return false; } @@ -254,37 +267,64 @@ size > getStdLanceSize(c.getFaction()) + 2) { } } + if (hasGround) { + ArrayList strategicFormations = campaign.getStrategicFormationList(); + List allLanceForceIds = new ArrayList<>(); + + for (StrategicFormation strategicFormation : strategicFormations) { + allLanceForceIds.add(strategicFormation.getForceId()); + } + + // Parent Forces + List parentForces = force.getAllParents(); + + for (Force parentForce : parentForces) { + if (allLanceForceIds.contains(parentForce.getId())) { + return false; + } + } + + // Child Forces + List childForces = force.getAllSubForces(); + + for (Force childForce : childForces) { + if (allLanceForceIds.contains(childForce.getId())) { + return false; + } + } + } + return hasGround; } /* Code to find unit commander from ForceViewPanel */ - public static UUID findCommander(int forceId, Campaign c) { - return c.getForce(forceId).getForceCommanderID(); + public static UUID findCommander(int forceId, Campaign campaign) { + return campaign.getForce(forceId).getForceCommanderID(); } public static LocalDate getBattleDate(LocalDate today) { return today.plusDays(Compute.randomInt(7)); } - public AtBScenario checkForBattle(Campaign c) { + public AtBScenario checkForBattle(Campaign campaign) { // Make sure there is a battle first - if ((c.getCampaignOptions().getAtBBattleChance(role) == 0) - || (Compute.randomInt(100) > c.getCampaignOptions().getAtBBattleChance(role))) { + if ((campaign.getCampaignOptions().getAtBBattleChance(role) == 0) + || (Compute.randomInt(100) > campaign.getCampaignOptions().getAtBBattleChance(role))) { // No battle return null; } // if we are using StratCon, don't *also* generate legacy scenarios - if (c.getCampaignOptions().isUseStratCon() && - (getContract(c).getStratconCampaignState() != null)) { + if (campaign.getCampaignOptions().isUseStratCon() && + (getContract(campaign).getStratconCampaignState() != null)) { return null; } int roll; // thresholds are coded from charts with 1-100 range, so we add 1 to mod to // adjust 0-based random int - int battleTypeMod = 1 + (AtBMoraleLevel.STALEMATE.ordinal() - getContract(c).getMoraleLevel().ordinal()) * 5; - battleTypeMod += getContract(c).getBattleTypeMod(); + int battleTypeMod = 1 + (AtBMoraleLevel.STALEMATE.ordinal() - getContract(campaign).getMoraleLevel().ordinal()) * 5; + battleTypeMod += getContract(campaign).getBattleTypeMod(); // debugging code that will allow you to force the generation of a particular // scenario. @@ -294,8 +334,8 @@ public AtBScenario checkForBattle(Campaign c) { /* * if (true) { - * AtBScenario scenario = AtBScenarioFactory.createScenario(c, this, - * AtBScenario.BASEATTACK, true, getBattleDate(c.getLocalDate())); + * AtBScenario scenario = AtBScenarioFactory.createScenario(campaign, this, + * AtBScenario.BASEATTACK, true, getBattleDate(campaign.getLocalDate())); * scenario.setMissionId(this.getMissionId()); * return scenario; * } @@ -305,144 +345,144 @@ public AtBScenario checkForBattle(Campaign c) { case FIGHTING: { roll = Compute.randomInt(40) + battleTypeMod; if (roll < 1) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BASEATTACK, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 9) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BREAKTHROUGH, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 17) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.STANDUP, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 25) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.STANDUP, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 33) { - if (c.getCampaignOptions().isGenerateChases()) { - return AtBScenarioFactory.createScenario(c, this, + if (campaign.getCampaignOptions().isGenerateChases()) { + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.CHASE, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HOLDTHELINE, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } } else if (roll < 41) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HOLDTHELINE, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BASEATTACK, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } } case SCOUTING: { roll = Compute.randomInt(60) + battleTypeMod; if (roll < 1) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BASEATTACK, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 11) { - if (c.getCampaignOptions().isGenerateChases()) { - return AtBScenarioFactory.createScenario(c, this, + if (campaign.getCampaignOptions().isGenerateChases()) { + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.CHASE, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HIDEANDSEEK, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } } else if (roll < 21) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HIDEANDSEEK, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 31) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.PROBE, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 41) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.PROBE, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 51) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.EXTRACTION, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.RECONRAID, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } } case DEFENCE: { roll = Compute.randomInt(20) + battleTypeMod; if (roll < 1) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BASEATTACK, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 5) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HOLDTHELINE, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 9) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.RECONRAID, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 13) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.EXTRACTION, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 17) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HIDEANDSEEK, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BREAKTHROUGH, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } } case TRAINING: { roll = Compute.randomInt(10) + battleTypeMod; if (roll < 1) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BASEATTACK, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 3) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HOLDTHELINE, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 5) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BREAKTHROUGH, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else if (roll < 7) { - if (c.getCampaignOptions().isGenerateChases()) { - return AtBScenarioFactory.createScenario(c, this, + if (campaign.getCampaignOptions().isGenerateChases()) { + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.CHASE, true, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.BREAKTHROUGH, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } } else if (roll < 9) { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HIDEANDSEEK, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - if (c.getCampaignOptions().isGenerateChases()) { - return AtBScenarioFactory.createScenario(c, this, + if (campaign.getCampaignOptions().isGenerateChases()) { + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.CHASE, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } else { - return AtBScenarioFactory.createScenario(c, this, + return AtBScenarioFactory.createScenario(campaign, this, AtBScenario.HOLDTHELINE, false, - getBattleDate(c.getLocalDate())); + getBattleDate(campaign.getLocalDate())); } } } @@ -461,13 +501,13 @@ public void writeToXML(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLCloseTag(pw, --indent, "lance"); } - public static Lance generateInstanceFromXML(Node wn) { - Lance retVal = null; + public static StrategicFormation generateInstanceFromXML(Node wn) { + StrategicFormation retVal = null; NamedNodeMap attrs = wn.getAttributes(); Node classNameNode = attrs.getNamedItem("type"); String className = classNameNode.getTextContent(); try { - retVal = (Lance) Class.forName(className).newInstance(); + retVal = (StrategicFormation) Class.forName(className).newInstance(); NodeList nl = wn.getChildNodes(); for (int x = 0; x < nl.getLength(); x++) { @@ -496,11 +536,11 @@ public static Lance generateInstanceFromXML(Node wn) { * @param forceId Force for which to calculate weight * @return Total force weight */ - public static double calculateTotalWeight(Campaign c, int forceId) { + public static double calculateTotalWeight(Campaign campaign, int forceId) { double weight = 0.0; - for (UUID id : c.getForce(forceId).getUnits()) { - Unit unit = c.getUnit(id); + for (UUID id : campaign.getForce(forceId).getUnits()) { + Unit unit = campaign.getUnit(id); if (null != unit) { Entity entity = unit.getEntity(); if (null != entity) { @@ -509,13 +549,13 @@ public static double calculateTotalWeight(Campaign c, int forceId) { (entity.getEntityType() & Entity.ETYPE_INFANTRY) != 0) { weight += entity.getWeight(); } else if ((entity.getEntityType() & Entity.ETYPE_TANK) != 0) { - if (c.getFaction().isClan() || c.getCampaignOptions().isAdjustPlayerVehicles()) { + if (campaign.getFaction().isClan() || campaign.getCampaignOptions().isAdjustPlayerVehicles()) { weight += entity.getWeight() * 0.5; } else { weight += entity.getWeight(); } } else if ((entity.getEntityType() & Entity.ETYPE_AEROSPACEFIGHTER) != 0) { - if (c.getFaction().isClan()) { + if (campaign.getFaction().isClan()) { weight += entity.getWeight() * 0.5; } else { weight += entity.getWeight(); diff --git a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java index ec4b0c7806..fdd374c545 100644 --- a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java +++ b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java @@ -35,7 +35,7 @@ import mekhq.campaign.againstTheBot.AtBConfiguration; import mekhq.campaign.finances.Finances; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.icons.UnitIcon; import mekhq.campaign.market.PersonnelMarket; import mekhq.campaign.market.ShoppingList; @@ -345,10 +345,10 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { // determine if we've missed any lances and add those back into the campaign if (options.isUseAtB()) { - Hashtable lances = retVal.getLances(); + Hashtable lances = retVal.getStrategicFormations(); for (Force f : retVal.getAllForces()) { if (!f.getUnits().isEmpty() && (null == lances.get(f.getId()))) { - lances.put(f.getId(), new Lance(f.getId(), retVal)); + lances.put(f.getId(), new StrategicFormation(f.getId(), retVal)); logger.warn(String.format("Added missing Lance %s to AtB list", f.getName())); } } @@ -778,7 +778,7 @@ private static void processLanceNodes(Campaign retVal, Node wn) { continue; } - Lance l = Lance.generateInstanceFromXML(wn2); + StrategicFormation l = StrategicFormation.generateInstanceFromXML(wn2); if (l != null) { retVal.importLance(l); diff --git a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenario.java b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenario.java index 0e761eda07..f651f572f7 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenario.java @@ -23,7 +23,7 @@ import megamek.common.annotations.Nullable; import megamek.common.enums.SkillLevel; import mekhq.campaign.Campaign; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.mission.ScenarioForceTemplate.ForceGenerationMethod; import mekhq.campaign.mission.atb.AtBScenarioModifier; import mekhq.campaign.personnel.Person; @@ -371,11 +371,11 @@ public Person getLanceCommander(Campaign campaign) { return null; // if we don't have forces, just a bunch of units, then get the highest-ranked? } - Lance lance = campaign.getLances().get(getForceIDs().get(0)); + StrategicFormation strategicFormation = campaign.getStrategicFormations().get(getForceIDs().get(0)); - if (lance != null) { - lance.refreshCommander(campaign); - return lance.getCommander(campaign); + if (strategicFormation != null) { + strategicFormation.refreshCommander(campaign); + return strategicFormation.getCommander(campaign); } else { return null; } diff --git a/MekHQ/src/mekhq/campaign/mission/AtBScenario.java b/MekHQ/src/mekhq/campaign/mission/AtBScenario.java index d8ccf140f5..556c53c1fc 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBScenario.java @@ -21,34 +21,19 @@ */ package mekhq.campaign.mission; -import java.io.PrintWriter; -import java.text.ParseException; -import java.time.LocalDate; -import java.util.*; - -import megamek.common.*; -import megamek.common.util.fileUtils.MegaMekFile; -import megamek.utilities.BoardClassifier; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import megamek.Version; import megamek.client.generator.TeamLoadOutGenerator; import megamek.codeUtilities.ObjectUtility; +import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.enums.SkillLevel; import megamek.common.icons.Camouflage; import megamek.common.options.OptionsConstants; import megamek.common.planetaryconditions.Atmosphere; -import megamek.common.planetaryconditions.BlowingSand; -import megamek.common.planetaryconditions.EMI; -import megamek.common.planetaryconditions.Fog; -import megamek.common.planetaryconditions.Light; -import megamek.common.planetaryconditions.PlanetaryConditions; -import megamek.common.planetaryconditions.Weather; -import megamek.common.planetaryconditions.Wind; +import megamek.common.planetaryconditions.*; +import megamek.common.util.fileUtils.MegaMekFile; import megamek.logging.MMLogger; +import megamek.utilities.BoardClassifier; import mekhq.MHQConstants; import mekhq.MekHQ; import mekhq.Utilities; @@ -56,7 +41,7 @@ import mekhq.campaign.againstTheBot.AtBConfiguration; import mekhq.campaign.againstTheBot.AtBStaticWeightGenerator; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.mission.ObjectiveEffect.ObjectiveEffectType; import mekhq.campaign.mission.ScenarioObjective.ObjectiveCriterion; import mekhq.campaign.mission.atb.IAtBScenario; @@ -66,12 +51,16 @@ import mekhq.campaign.stratcon.StratconBiomeManifest; import mekhq.campaign.stratcon.StratconBiomeManifest.MapTypeList; import mekhq.campaign.unit.Unit; -import mekhq.campaign.universe.Faction; -import mekhq.campaign.universe.Factions; -import mekhq.campaign.universe.Planet; -import mekhq.campaign.universe.PlanetarySystem; -import mekhq.campaign.universe.Systems; +import mekhq.campaign.universe.*; import mekhq.utilities.MHQXMLUtility; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintWriter; +import java.text.ParseException; +import java.time.LocalDate; +import java.util.*; /** * @author Neoancient @@ -154,7 +143,7 @@ public abstract class AtBScenario extends Scenario implements IAtBScenario { public static final int NO_LANCE = -1; private boolean attacker; - private int lanceForceId; // -1 if scenario is not generated for a specific lance (special scenario, big + private int strategicFormationId; // -1 if scenario is not generated for a specific lance (special scenario, big // battle) private AtBLanceRole lanceRole; /* * set when scenario is created in case it is changed for the next week before @@ -218,7 +207,7 @@ public abstract class AtBScenario extends Scenario implements IAtBScenario { public AtBScenario() { super(); - lanceForceId = -1; + strategicFormationId = -1; lanceRole = AtBLanceRole.UNASSIGNED; alliesPlayer = new ArrayList<>(); alliesPlayerStub = new ArrayList<>(); @@ -235,7 +224,7 @@ public AtBScenario() { SB = StratconBiomeManifest.getInstance(); } - public void initialize(Campaign c, Lance lance, boolean attacker, LocalDate date) { + public void initialize(Campaign c, StrategicFormation lance, boolean attacker, LocalDate date) { setAttacker(attacker); alliesPlayer = new ArrayList<>(); @@ -247,10 +236,10 @@ public void initialize(Campaign c, Lance lance, boolean attacker, LocalDate date entityIds = new HashMap<>(); if (null == lance) { - lanceForceId = -1; + strategicFormationId = -1; lanceRole = AtBLanceRole.UNASSIGNED; } else { - this.lanceForceId = lance.getForceId(); + this.strategicFormationId = lance.getForceId(); lanceRole = lance.getRole(); setMissionId(lance.getMissionId()); @@ -337,10 +326,10 @@ private void initBattle(Campaign campaign) { lanceCount = 2; } - if (null != getLance(campaign)) { - getLance(campaign).refreshCommander(campaign); - if (null != getLance(campaign).getCommander(campaign).getSkill(SkillType.S_TACTICS)) { - rerollsRemaining = getLance(campaign).getCommander(campaign).getSkill(SkillType.S_TACTICS).getLevel(); + if (null != getStrategicFormation(campaign)) { + getStrategicFormation(campaign).refreshCommander(campaign); + if (null != getStrategicFormation(campaign).getCommander(campaign).getSkill(SkillType.S_TACTICS)) { + rerollsRemaining = getStrategicFormation(campaign).getCommander(campaign).getSkill(SkillType.S_TACTICS).getLevel(); } } } @@ -899,7 +888,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(getAllyBotForce(getContract(campaign), getStartingPos(), playerHome, allyEntities), campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), campaign); + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), campaign); addBotForce(getEnemyBotForce(getContract(campaign), enemyHome, enemyHome, enemyEntities), campaign); } @@ -1651,7 +1640,7 @@ protected void setObjectives(Campaign c, AtBContract contract) { @Override protected void writeToXMLEnd(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "attacker", isAttacker()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "lanceForceId", lanceForceId); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "lanceForceId", strategicFormationId); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "lanceRole", lanceRole.name()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "deploymentDelay", deploymentDelay); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "lanceCount", lanceCount); @@ -1745,7 +1734,7 @@ protected void loadFieldsFromXmlNode(final Node wn, final Version version, final if (wn2.getNodeName().equalsIgnoreCase("attacker")) { setAttacker(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("lanceForceId")) { - lanceForceId = Integer.parseInt(wn2.getTextContent()); + strategicFormationId = Integer.parseInt(wn2.getTextContent()); } else if (wn2.getNodeName().equalsIgnoreCase("lanceRole")) { lanceRole = AtBLanceRole.parseFromString(wn2.getTextContent().trim()); } else if (wn2.getNodeName().equalsIgnoreCase("deploymentDelay")) { @@ -1973,20 +1962,20 @@ public List filterUntransportedUnits(List entities) { return retVal; } - public int getLanceForceId() { - return lanceForceId; + public int getStrategicFormationId() { + return strategicFormationId; } public AtBLanceRole getLanceRole() { return lanceRole; } - public Lance getLance(Campaign c) { - return c.getLances().get(lanceForceId); + public StrategicFormation getStrategicFormation(Campaign campaign) { + return campaign.getStrategicFormations().get(strategicFormationId); } - public void setLance(Lance l) { - lanceForceId = l.getForceId(); + public void setLance(StrategicFormation strategicFormation) { + strategicFormationId = strategicFormation.getForceId(); } /** diff --git a/MekHQ/src/mekhq/campaign/mission/CommonObjectiveFactory.java b/MekHQ/src/mekhq/campaign/mission/CommonObjectiveFactory.java index a9e15a7c77..bdb8938f83 100644 --- a/MekHQ/src/mekhq/campaign/mission/CommonObjectiveFactory.java +++ b/MekHQ/src/mekhq/campaign/mission/CommonObjectiveFactory.java @@ -37,7 +37,7 @@ * */ public class CommonObjectiveFactory { - private static final transient ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.AtBScenarioBuiltIn", + private static final ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.AtBScenarioBuiltIn", MekHQ.getMHQOptions().getLocale()); /** @@ -77,7 +77,7 @@ public static ScenarioObjective getPreserveSpecificFriendlies(String forceName, keepFriendliesAlive.setDescription(String.format(resourceMap.getString("commonObjectives.preserveFriendlyUnits.text"), number, "")); keepFriendliesAlive.setFixedAmount(number); } else { - keepFriendliesAlive.setDescription(String.format(resourceMap.getString("commonObjectives.preserveFriendlyUnits.text"), number, "%")); + keepFriendliesAlive.setDescription(String.format(resourceMap.getString("commonObjectives.preserveFriendlyUnits.text"), number, '%')); keepFriendliesAlive.setPercentage(number); } keepFriendliesAlive.setObjectiveCriterion(ObjectiveCriterion.Preserve); @@ -108,7 +108,7 @@ public static ScenarioObjective getKeepFriendliesAlive(Campaign campaign, AtBCon keepFriendliesAlive.setDescription(String.format(resourceMap.getString("commonObjectives.preserveFriendlyUnits.text"), number, "")); keepFriendliesAlive.setFixedAmount(number); } else { - keepFriendliesAlive.setDescription(String.format(resourceMap.getString("commonObjectives.preserveFriendlyUnits.text"), number, "%")); + keepFriendliesAlive.setDescription(String.format(resourceMap.getString("commonObjectives.preserveFriendlyUnits.text"), number, '%')); keepFriendliesAlive.setPercentage(number); } @@ -228,8 +228,8 @@ private static void addAssignedPlayerUnitsToObjective(AtBScenario scenario, Camp // some scenarios have a lance assigned // some scenarios have individual units assigned - if (scenario.getLanceForceId() != AtBScenario.NO_LANCE) { - objective.addForce(campaign.getForce(scenario.getLanceForceId()).getName()); + if (scenario.getStrategicFormationId() != AtBScenario.NO_LANCE) { + objective.addForce(campaign.getForce(scenario.getStrategicFormationId()).getName()); } else { int unitCount = 0; diff --git a/MekHQ/src/mekhq/campaign/mission/atb/AtBScenarioFactory.java b/MekHQ/src/mekhq/campaign/mission/atb/AtBScenarioFactory.java index cb63e6ff0b..540468ad61 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/AtBScenarioFactory.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/AtBScenarioFactory.java @@ -21,7 +21,7 @@ import megamek.codeUtilities.ObjectUtility; import megamek.logging.MMLogger; import mekhq.campaign.Campaign; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.mission.AtBContract; import mekhq.campaign.mission.AtBScenario; import mekhq.campaign.mission.atb.scenario.*; @@ -67,7 +67,7 @@ public static List> getScenarios(int type) { return scenarioMap.get(type); } - public static AtBScenario createScenario(Campaign c, Lance lance, int type, boolean attacker, LocalDate date) { + public static AtBScenario createScenario(Campaign c, StrategicFormation lance, int type, boolean attacker, LocalDate date) { List> classList = getScenarios(type); Class selectedClass; @@ -117,16 +117,16 @@ public static void registerScenario(IAtBScenario scenario) { * * Note that this handles having multiple active contracts at the same time * - * @param c the campaign for which to generate scenarios + * @param campaign the campaign for which to generate scenarios */ - public static void createScenariosForNewWeek(Campaign c) { + public static void createScenariosForNewWeek(Campaign campaign) { // First, we only want to generate if we have an active contract - if (!c.hasActiveContract()) { + if (!campaign.hasActiveContract()) { return; } // If we have an active contract, then we can progress with generation - Hashtable lances = c.getLances(); + Hashtable strategicFormations = campaign.getStrategicFormations(); List sList; List assignedLances = new ArrayList<>(); @@ -135,7 +135,7 @@ public static void createScenariosForNewWeek(Campaign c) { boolean hasBaseAttackAttacker; // We only need to process active AtB contracts that haven't hit their end date - for (final AtBContract contract : c.getActiveAtBContracts()) { + for (final AtBContract contract : campaign.getActiveAtBContracts()) { // region Value Initialization sList = new ArrayList<>(); dontGenerateForces = new ArrayList<>(); @@ -151,8 +151,8 @@ public static void createScenariosForNewWeek(Campaign c) { // the generation rules are followed for all active scenarios not just new // scenarios for (final AtBScenario scenario : contract.getCurrentAtBScenarios()) { - // Add any currently assigned lances to the assignedLances - assignedLances.add(scenario.getLanceForceId()); + // Add any currently assigned strategicFormations to the assignedLances + assignedLances.add(scenario.getStrategicFormationId()); // Remove any active scenarios from the contract, and add them to the current // scenarios list instead @@ -174,14 +174,14 @@ public static void createScenariosForNewWeek(Campaign c) { // endregion Current Scenarios // region Generate Scenarios - // Generate scenarios for lances based on their current situation + // Generate scenarios for strategicFormations based on their current situation if (!hasBaseAttackAttacker) { - for (Lance lance : lances.values()) { - // Don't generate scenarios for any lances already assigned, those assigned to a - // different contract, those not assigned to a contract, or for illegible lances - if (assignedLances.contains(lance.getForceId()) || (lance.getContract(c) == null) - || !lance.isEligible(c) || (lance.getMissionId() != contract.getId()) - || !lance.getContract(c).isActiveOn(c.getLocalDate(), true)) { + for (StrategicFormation strategicFormation : strategicFormations.values()) { + // Don't generate scenarios for any strategicFormations already assigned, those assigned to a + // different contract, those not assigned to a contract, or for illegible strategicFormations + if (assignedLances.contains(strategicFormation.getForceId()) || (strategicFormation.getContract(campaign) == null) + || !strategicFormation.isEligible(campaign) || (strategicFormation.getMissionId() != contract.getId()) + || !strategicFormation.getContract(campaign).isActiveOn(campaign.getLocalDate(), true)) { continue; } @@ -191,13 +191,13 @@ public static void createScenariosForNewWeek(Campaign c) { continue; } - // Attempt to generate a scenario for the lance - AtBScenario scenario = lance.checkForBattle(c); + // Attempt to generate a scenario for the strategicFormation + AtBScenario scenario = strategicFormation.checkForBattle(campaign); // If one is generated, then add it to the scenario list if (scenario != null) { sList.add(scenario); - assignedLances.add(lance.getForceId()); + assignedLances.add(strategicFormation.getForceId()); // We care if the scenario is a Base Attack, as one must be generated if the // current contract's morale is Unbreakable @@ -219,45 +219,46 @@ public static void createScenariosForNewWeek(Campaign c) { // region Overwhelming Morale Missions // Make sure Overwhelming morale missions have a base attack scenario generated - if (!c.getCampaignOptions().isUseStratCon()) { + if (!campaign.getCampaignOptions().isUseStratCon()) { if (!hasBaseAttack && contract.getMoraleLevel().isOverwhelming()) { /* * find a lance to act as defender, giving preference * first to those assigned to the same contract, * then to those assigned to defense roles */ - List lList = new ArrayList<>(); - for (Lance l : lances.values()) { - if ((l.getMissionId() == contract.getId()) && l.getRole().isDefence() && l.isEligible(c)) { - lList.add(l); + List lList = new ArrayList<>(); + for (StrategicFormation strategicFormation : strategicFormations.values()) { + if ((strategicFormation.getMissionId() == contract.getId()) + && strategicFormation.getRole().isDefence() && strategicFormation.isEligible(campaign)) { + lList.add(strategicFormation); } } if (lList.isEmpty()) { - for (Lance l : lances.values()) { - if ((l.getMissionId() == contract.getId()) && l.isEligible(c)) { - lList.add(l); + for (StrategicFormation strategicFormation : strategicFormations.values()) { + if ((strategicFormation.getMissionId() == contract.getId()) && strategicFormation.isEligible(campaign)) { + lList.add(strategicFormation); } } } if (lList.isEmpty()) { - for (Lance l : lances.values()) { - if (l.isEligible(c)) { - lList.add(l); + for (StrategicFormation strategicFormation : strategicFormations.values()) { + if (strategicFormation.isEligible(campaign)) { + lList.add(strategicFormation); } } } if (!lList.isEmpty()) { - Lance lance = ObjectUtility.getRandomItem(lList); - AtBScenario atbScenario = AtBScenarioFactory.createScenario(c, lance, - AtBScenario.BASEATTACK, false, Lance.getBattleDate(c.getLocalDate())); + StrategicFormation strategicFormation = ObjectUtility.getRandomItem(lList); + AtBScenario atbScenario = AtBScenarioFactory.createScenario(campaign, strategicFormation, + AtBScenario.BASEATTACK, false, StrategicFormation.getBattleDate(campaign.getLocalDate())); if (atbScenario != null) { - if ((lance.getMissionId() == atbScenario.getMissionId()) - || (lance.getMissionId() == Lance.NO_MISSION)) { + if ((strategicFormation.getMissionId() == atbScenario.getMissionId()) + || (strategicFormation.getMissionId() == StrategicFormation.NO_MISSION)) { for (int i = 0; i < sList.size(); i++) { - if (sList.get(i).getLanceForceId() == lance.getForceId()) { + if (sList.get(i).getStrategicFormationId() == strategicFormation.getForceId()) { if (dontGenerateForces.contains(atbScenario.getId())) { dontGenerateForces.remove(atbScenario.getId()); } @@ -266,23 +267,23 @@ public static void createScenariosForNewWeek(Campaign c) { } } } else { - // edge case: lance assigned to another mission gets assigned the scenario, + // edge case: strategicFormation assigned to another mission gets assigned the scenario, // we need to remove any scenario they are assigned to already - c.getMission(lance.getMissionId()).getScenarios() + campaign.getMission(strategicFormation.getMissionId()).getScenarios() .removeIf(scenario -> (scenario instanceof AtBScenario) - && (((AtBScenario) scenario).getLanceForceId() == lance.getForceId())); + && (((AtBScenario) scenario).getStrategicFormationId() == strategicFormation.getForceId())); } if (!sList.contains(atbScenario)) { sList.add(atbScenario); } - if (!assignedLances.contains(lance.getForceId())) { - assignedLances.add(lance.getForceId()); + if (!assignedLances.contains(strategicFormation.getForceId())) { + assignedLances.add(strategicFormation.getForceId()); } } else { logger.error("Unable to generate Base Attack scenario."); } } else { - logger.warn("No lances assigned to mission " + contract.getName() + logger.warn("No strategicFormations assigned to mission " + contract.getName() + ". Can't generate an Unbreakable Morale base defense mission for this force."); } } @@ -305,9 +306,9 @@ public static void createScenariosForNewWeek(Campaign c) { // for the scenario if required sList.sort((s1, s2) -> ObjectUtility.compareNullable(s1.getDate(), s2.getDate(), LocalDate::compareTo)); for (AtBScenario atbScenario : sList) { - c.addScenario(atbScenario, contract); + campaign.addScenario(atbScenario, contract); if (!dontGenerateForces.contains(atbScenario.getId())) { - atbScenario.setForces(c); + atbScenario.setForces(campaign); } } // endregion Add to Campaign diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/BaseAttackBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/BaseAttackBuiltInScenario.java index aba45e9a29..62286ce795 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/BaseAttackBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/BaseAttackBuiltInScenario.java @@ -18,23 +18,18 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; - import megamek.client.bot.princess.BehaviorSettingsFactory; import megamek.common.Board; import megamek.common.Compute; import megamek.common.Entity; import megamek.common.EntityWeightClass; import mekhq.campaign.Campaign; -import mekhq.campaign.mission.enums.AtBLanceRole; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.BotForce; -import mekhq.campaign.mission.CommonObjectiveFactory; -import mekhq.campaign.mission.ObjectiveEffect; -import mekhq.campaign.mission.ScenarioObjective; +import mekhq.campaign.mission.*; import mekhq.campaign.mission.ObjectiveEffect.ObjectiveEffectType; import mekhq.campaign.mission.atb.AtBScenarioEnabled; +import mekhq.campaign.mission.enums.AtBLanceRole; + +import java.util.ArrayList; @AtBScenarioEnabled public class BaseAttackBuiltInScenario extends AtBScenario { @@ -103,7 +98,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti * Ally deploys 2 lances of a lighter weight class than the player, * minimum light */ - int allyForceWeight = Math.max(getLance(campaign).getWeightClass(campaign) - 1, EntityWeightClass.WEIGHT_LIGHT); + int allyForceWeight = Math.max(getStrategicFormation(campaign).getWeightClass(campaign) - 1, EntityWeightClass.WEIGHT_LIGHT); addLance(allyEntities, getContract(campaign).getEmployerCode(), getContract(campaign).getAllySkill(), getContract(campaign).getAllyQuality(), allyForceWeight, campaign); addLance(allyEntities, getContract(campaign).getEmployerCode(), getContract(campaign).getAllySkill(), @@ -143,14 +138,14 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(new BotForce(BASE_TURRET_FORCE_ID, isAttacker() ? 2 : 1, defenderStart, defenderHome, turretForce), campaign); /* Roll 2x on bot lances roll */ - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), campaign); + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), campaign); addBotForce(getEnemyBotForce(getContract(campaign), enemyStart, getEnemyHome(), enemyEntities), campaign); // the "second" enemy force will either flee in the same direction as // the first enemy force in case of the player being the attacker // or where it came from in case of player being defender ArrayList secondBotEntities = new ArrayList<>(); - addEnemyForce(secondBotEntities, getLance(campaign).getWeightClass(campaign), campaign); + addEnemyForce(secondBotEntities, getStrategicFormation(campaign).getWeightClass(campaign), campaign); BotForce secondBotForce = getEnemyBotForce(getContract(campaign), isAttacker() ? enemyStart : secondAttackerForceStart, isAttacker() ? getEnemyHome() : secondAttackerForceStart, secondBotEntities); diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/BreakthroughBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/BreakthroughBuiltInScenario.java index 501354caec..38ef0705fb 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/BreakthroughBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/BreakthroughBuiltInScenario.java @@ -18,8 +18,6 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; - import megamek.client.bot.princess.BehaviorSettingsFactory; import megamek.common.Board; import megamek.common.Compute; @@ -27,14 +25,11 @@ import megamek.common.OffBoardDirection; import megamek.logging.MMLogger; import mekhq.campaign.Campaign; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBDynamicScenarioFactory; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.BotForce; -import mekhq.campaign.mission.CommonObjectiveFactory; -import mekhq.campaign.mission.ScenarioObjective; +import mekhq.campaign.mission.*; import mekhq.campaign.mission.atb.AtBScenarioEnabled; +import java.util.ArrayList; + @AtBScenarioEnabled public class BreakthroughBuiltInScenario extends AtBScenario { private static final MMLogger logger = MMLogger.create(BreakthroughBuiltInScenario.class); @@ -97,7 +92,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(allyEntitiesForce, campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), campaign); + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), campaign); BotForce botForce = getEnemyBotForce(getContract(campaign), enemyStart, getEnemyHome(), enemyEntities); try { diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ChaseBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ChaseBuiltInScenario.java index 3bc4250aca..a52b493173 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ChaseBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ChaseBuiltInScenario.java @@ -18,25 +18,16 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; - import megamek.client.bot.princess.BehaviorSettingsFactory; import megamek.client.bot.princess.PrincessException; -import megamek.common.Board; -import megamek.common.Compute; -import megamek.common.Entity; -import megamek.common.EntityWeightClass; -import megamek.common.OffBoardDirection; +import megamek.common.*; import megamek.logging.MMLogger; import mekhq.campaign.Campaign; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBDynamicScenarioFactory; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.BotForce; -import mekhq.campaign.mission.CommonObjectiveFactory; -import mekhq.campaign.mission.ScenarioObjective; +import mekhq.campaign.mission.*; import mekhq.campaign.mission.atb.AtBScenarioEnabled; +import java.util.ArrayList; + @AtBScenarioEnabled public class ChaseBuiltInScenario extends AtBScenario { private static final MMLogger logger = MMLogger.create(ChaseBuiltInScenario.class); @@ -89,9 +80,9 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(allyEntitiesForce, campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_ASSAULT, 0, + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_ASSAULT, 0, -1, campaign); - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_ASSAULT, 0, + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_ASSAULT, 0, -1, campaign); BotForce botForce = getEnemyBotForce(getContract(campaign), startEdge, getEnemyHome(), enemyEntities); @@ -121,7 +112,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti int speed = en.getWalkMP(); if (en.getJumpMP() > 0) { - if (en instanceof megamek.common.Infantry) { + if (en instanceof Infantry) { speed = en.getJumpMP(); } else { speed++; @@ -135,7 +126,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti int speed = en.getWalkMP(); if (en.getJumpMP() > 0) { - if (en instanceof megamek.common.Infantry) { + if (en instanceof Infantry) { speed = en.getJumpMP(); } else { speed++; diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ExtractionBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ExtractionBuiltInScenario.java index 0da9a9c6de..d81a7b29d2 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ExtractionBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ExtractionBuiltInScenario.java @@ -18,9 +18,6 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; -import java.util.UUID; - import megamek.client.bot.princess.BehaviorSettingsFactory; import megamek.client.bot.princess.PrincessException; import megamek.common.Board; @@ -28,17 +25,15 @@ import megamek.common.Entity; import megamek.logging.MMLogger; import mekhq.campaign.Campaign; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.BotForce; -import mekhq.campaign.mission.CommonObjectiveFactory; -import mekhq.campaign.mission.ObjectiveEffect; +import mekhq.campaign.mission.*; import mekhq.campaign.mission.ObjectiveEffect.EffectScalingType; import mekhq.campaign.mission.ObjectiveEffect.ObjectiveEffectType; -import mekhq.campaign.mission.ScenarioObjective; import mekhq.campaign.mission.ScenarioObjective.TimeLimitType; import mekhq.campaign.mission.atb.AtBScenarioEnabled; +import java.util.ArrayList; +import java.util.UUID; + @AtBScenarioEnabled public class ExtractionBuiltInScenario extends AtBScenario { private static final MMLogger logger = MMLogger.create(ExtractionBuiltInScenario.class); @@ -103,7 +98,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(getAllyBotForce(getContract(campaign), getStartingPos(), playerHome, allyEntities), campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), campaign); + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), campaign); addBotForce(getEnemyBotForce(getContract(campaign), enemyStart, getEnemyHome(), enemyEntities), campaign); ArrayList otherForce = new ArrayList<>(); diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/HideAndSeekBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/HideAndSeekBuiltInScenario.java index c0ff5c8ace..9f593f1c5a 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/HideAndSeekBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/HideAndSeekBuiltInScenario.java @@ -29,6 +29,7 @@ import mekhq.campaign.mission.ScenarioObjective; import mekhq.campaign.mission.atb.AtBScenarioEnabled; import mekhq.campaign.stratcon.StratconBiomeManifest; +import mekhq.campaign.stratcon.StratconBiomeManifest.MapTypeList; import java.util.ArrayList; import java.util.List; @@ -54,7 +55,7 @@ public String getResourceKey() { @Override public void setTerrain() { - Map mapTypes = StratconBiomeManifest.getInstance().getBiomeMapTypes(); + Map mapTypes = StratconBiomeManifest.getInstance().getBiomeMapTypes(); List keys = mapTypes.keySet().stream().sorted().collect(Collectors.toList()); do { setTerrainType(keys.get(Compute.randomInt(keys.size()))); @@ -107,10 +108,10 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti } if (isAttacker()) { - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_ASSAULT, 2, 0, campaign); } else { - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_HEAVY, 0, 0, campaign); } diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/HoldTheLineBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/HoldTheLineBuiltInScenario.java index 0b73a4c068..36bde06255 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/HoldTheLineBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/HoldTheLineBuiltInScenario.java @@ -18,8 +18,6 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; - import megamek.common.Board; import megamek.common.Compute; import megamek.common.Entity; @@ -31,6 +29,8 @@ import mekhq.campaign.mission.ScenarioObjective; import mekhq.campaign.mission.atb.AtBScenarioEnabled; +import java.util.ArrayList; + @AtBScenarioEnabled public class HoldTheLineBuiltInScenario extends AtBScenario { @Override @@ -79,7 +79,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(getAllyBotForce(getContract(campaign), getStartingPos(), playerHome, allyEntities), campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_ASSAULT, + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_ASSAULT, isAttacker() ? 0 : 4, 0, campaign); addBotForce(getEnemyBotForce(getContract(campaign), enemyStart, getEnemyHome(), enemyEntities), campaign); diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ProbeBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ProbeBuiltInScenario.java index 4a9a41ae9e..a18f653bb8 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ProbeBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ProbeBuiltInScenario.java @@ -18,11 +18,6 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - import megamek.common.Compute; import megamek.common.Entity; import megamek.common.EntityWeightClass; @@ -33,6 +28,12 @@ import mekhq.campaign.mission.ScenarioObjective; import mekhq.campaign.mission.atb.AtBScenarioEnabled; import mekhq.campaign.stratcon.StratconBiomeManifest; +import mekhq.campaign.stratcon.StratconBiomeManifest.MapTypeList; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @AtBScenarioEnabled public class ProbeBuiltInScenario extends AtBScenario { @@ -53,7 +54,7 @@ public String getResourceKey() { @Override public void setTerrain() { - Map mapTypes = StratconBiomeManifest.getInstance().getBiomeMapTypes(); + Map mapTypes = StratconBiomeManifest.getInstance().getBiomeMapTypes(); List keys = mapTypes.keySet().stream().sorted().collect(Collectors.toList()); do { setTerrainType(keys.get(Compute.randomInt(keys.size()))); @@ -78,7 +79,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(getAllyBotForce(getContract(campaign), getStartingPos(), playerHome, allyEntities), campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_MEDIUM, 0, 0, + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), EntityWeightClass.WEIGHT_MEDIUM, 0, 0, campaign); addBotForce(getEnemyBotForce(getContract(campaign), enemyStart, getEnemyHome(), enemyEntities), campaign); diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ReconRaidBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ReconRaidBuiltInScenario.java index 9033a63e68..f547848e72 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/ReconRaidBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/ReconRaidBuiltInScenario.java @@ -18,25 +18,16 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; - -import megamek.common.Board; -import megamek.common.Compute; -import megamek.common.Entity; -import megamek.common.EntityWeightClass; -import megamek.common.OffBoardDirection; +import megamek.common.*; import mekhq.campaign.Campaign; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBDynamicScenarioFactory; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.CommonObjectiveFactory; -import mekhq.campaign.mission.ObjectiveEffect; +import mekhq.campaign.mission.*; import mekhq.campaign.mission.ObjectiveEffect.ObjectiveEffectType; -import mekhq.campaign.mission.ScenarioObjective; import mekhq.campaign.mission.ScenarioObjective.ObjectiveCriterion; import mekhq.campaign.mission.ScenarioObjective.TimeLimitType; import mekhq.campaign.mission.atb.AtBScenarioEnabled; +import java.util.ArrayList; + @AtBScenarioEnabled public class ReconRaidBuiltInScenario extends AtBScenario { @Override @@ -85,7 +76,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(getAllyBotForce(getContract(campaign), getStartingPos(), playerHome, allyEntities), campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), isAttacker() ? EntityWeightClass.WEIGHT_ASSAULT : EntityWeightClass.WEIGHT_MEDIUM, 0, 0, campaign); addBotForce(getEnemyBotForce(getContract(campaign), enemyStart, getEnemyHome(), enemyEntities), campaign); diff --git a/MekHQ/src/mekhq/campaign/mission/atb/scenario/StandUpBuiltInScenario.java b/MekHQ/src/mekhq/campaign/mission/atb/scenario/StandUpBuiltInScenario.java index 1a01d05207..8e1ecb0dc7 100644 --- a/MekHQ/src/mekhq/campaign/mission/atb/scenario/StandUpBuiltInScenario.java +++ b/MekHQ/src/mekhq/campaign/mission/atb/scenario/StandUpBuiltInScenario.java @@ -18,8 +18,6 @@ */ package mekhq.campaign.mission.atb.scenario; -import java.util.ArrayList; - import megamek.common.Compute; import megamek.common.Entity; import mekhq.campaign.Campaign; @@ -29,6 +27,8 @@ import mekhq.campaign.mission.ScenarioObjective; import mekhq.campaign.mission.atb.AtBScenarioEnabled; +import java.util.ArrayList; + @AtBScenarioEnabled public class StandUpBuiltInScenario extends AtBScenario { @Override @@ -64,7 +64,7 @@ public void setExtraScenarioForces(Campaign campaign, ArrayList allyEnti addBotForce(getAllyBotForce(getContract(campaign), getStartingPos(), playerHome, allyEntities), campaign); } - addEnemyForce(enemyEntities, getLance(campaign).getWeightClass(campaign), campaign); + addEnemyForce(enemyEntities, getStrategicFormation(campaign).getWeightClass(campaign), campaign); addBotForce(getEnemyBotForce(getContract(campaign), getEnemyHome(), getEnemyHome(), enemyEntities), campaign); } diff --git a/MekHQ/src/mekhq/campaign/personnel/autoAwards/MiscAwards.java b/MekHQ/src/mekhq/campaign/personnel/autoAwards/MiscAwards.java index 6dcac12bec..db09548a5d 100644 --- a/MekHQ/src/mekhq/campaign/personnel/autoAwards/MiscAwards.java +++ b/MekHQ/src/mekhq/campaign/personnel/autoAwards/MiscAwards.java @@ -279,7 +279,7 @@ private static boolean prisonerOfWar(Campaign campaign, Award award, UUID person */ private static boolean drillInstructor(Campaign campaign, Award award, UUID person) { if (award.canBeAwarded(campaign.getPerson(person))) { - return campaign.getLanceList().stream() + return campaign.getStrategicFormationList().stream() .anyMatch(lance -> (lance.getRole().isTraining()) && (lance.getCommanderId().equals(person))); } diff --git a/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java b/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java index 65ad62de22..7d63ffb606 100644 --- a/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java +++ b/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java @@ -33,7 +33,7 @@ import mekhq.campaign.event.ScenarioChangedEvent; import mekhq.campaign.event.StratconDeploymentEvent; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.mission.*; import mekhq.campaign.mission.ScenarioForceTemplate.ForceAlignment; import mekhq.campaign.mission.ScenarioForceTemplate.ForceGenerationMethod; @@ -833,7 +833,7 @@ public static void processForceDeployment(StratconCoords coords, int forceID, Ca MekHQ.triggerEvent(new ScenarioChangedEvent(scenario.getBackingScenario())); } - if (campaign.getLances().get(forceID).getRole().isScouting()) { + if (campaign.getStrategicFormations().get(forceID).getRole().isScouting()) { for (int direction = 0; direction < 6; direction++) { StratconCoords checkCoords = coords.translate(direction); @@ -1043,7 +1043,7 @@ private static boolean commanderLanceHasDefensiveAssignment(AtBDynamicScenario s if (lanceCommander != null){ Unit commanderUnit = lanceCommander.getUnit(); if (commanderUnit != null) { - Lance lance = campaign.getLances().get(commanderUnit.getForceId()); + StrategicFormation lance = campaign.getStrategicFormations().get(commanderUnit.getForceId()); return (lance != null) && lance.getRole().isDefence(); } @@ -1415,7 +1415,7 @@ public static List getAvailableForceIDs(Campaign campaign) { // that are // deployed to a scenario and not in a track already - return campaign.getLances().keySet().stream() + return campaign.getStrategicFormations().keySet().stream() .mapToInt(key -> key) .mapToObj(campaign::getForce).filter(force -> (force != null) && !force.isDeployed() @@ -1451,7 +1451,7 @@ public static List getAvailableForceIDs(int unitType, Campaign campaign forcesInTracks.addAll(currentScenario.getFailedReinforcements()); } - for (int key : campaign.getLances().keySet()) { + for (int key : campaign.getStrategicFormations().keySet()) { Force force = campaign.getForce(key); if (force == null) { @@ -1672,8 +1672,8 @@ public static ReinforcementEligibilityType getReinforcementType(int forceID, Str // if the force is in 'fight' stance, it'll be able to deploy using 'fight // lance' rules - if (campaign.getLances().containsKey(forceID) - && (campaign.getLances().get(forceID).getRole().isFighting())) { + if (campaign.getStrategicFormations().containsKey(forceID) + && (campaign.getStrategicFormations().get(forceID).getRole().isFighting())) { return ReinforcementEligibilityType.FightLance; } diff --git a/MekHQ/src/mekhq/gui/BriefingTab.java b/MekHQ/src/mekhq/gui/BriefingTab.java index 741bb29fc2..5d93ecf1b1 100644 --- a/MekHQ/src/mekhq/gui/BriefingTab.java +++ b/MekHQ/src/mekhq/gui/BriefingTab.java @@ -38,7 +38,7 @@ import mekhq.campaign.event.*; import mekhq.campaign.finances.Money; import mekhq.campaign.finances.enums.TransactionType; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.mission.*; import mekhq.campaign.mission.atb.AtBScenarioFactory; import mekhq.campaign.mission.enums.MissionStatus; @@ -893,11 +893,11 @@ private void startScenario() { // code to support deployment of reinforcements for legacy ATB scenarios. if ((scenario instanceof AtBScenario) && !(scenario instanceof AtBDynamicScenario)) { - Lance assignedLance = ((AtBScenario) scenario).getLance(getCampaign()); + StrategicFormation assignedLance = ((AtBScenario) scenario).getStrategicFormation(getCampaign()); if (assignedLance != null) { int assignedForceId = assignedLance.getForceId(); int cmdrStrategy = 0; - Person commander = getCampaign().getPerson(Lance.findCommander(assignedForceId, getCampaign())); + Person commander = getCampaign().getPerson(StrategicFormation.findCommander(assignedForceId, getCampaign())); if ((null != commander) && (null != commander.getSkill(SkillType.S_STRATEGY))) { cmdrStrategy = commander.getSkill(SkillType.S_STRATEGY).getLevel(); } diff --git a/MekHQ/src/mekhq/gui/stratcon/ScenarioWizardLanceRenderer.java b/MekHQ/src/mekhq/gui/stratcon/ScenarioWizardLanceRenderer.java index 56f4ce110a..e9b8747f8f 100644 --- a/MekHQ/src/mekhq/gui/stratcon/ScenarioWizardLanceRenderer.java +++ b/MekHQ/src/mekhq/gui/stratcon/ScenarioWizardLanceRenderer.java @@ -20,7 +20,7 @@ import mekhq.campaign.Campaign; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import javax.swing.*; import java.awt.*; @@ -50,7 +50,7 @@ public Component getListCellRendererComponent(final JList list, setForeground(foreground); setBackground(background); - Lance lance = campaign.getLances().get(value.getId()); + StrategicFormation lance = campaign.getStrategicFormations().get(value.getId()); String roleString = ""; if (lance != null) { roleString = lance.getRole().toString() + ", "; diff --git a/MekHQ/src/mekhq/gui/view/AtBScenarioViewPanel.java b/MekHQ/src/mekhq/gui/view/AtBScenarioViewPanel.java index 50fd9de1e8..ebee91f81a 100644 --- a/MekHQ/src/mekhq/gui/view/AtBScenarioViewPanel.java +++ b/MekHQ/src/mekhq/gui/view/AtBScenarioViewPanel.java @@ -292,8 +292,8 @@ private void fillStats() { gridBagConstraints.gridwidth = 1; panStats.add(lblForce, gridBagConstraints); - if (null != scenario.getLance(campaign)) { - lblForceDesc.setText(campaign.getForce(scenario.getLanceForceId()).getFullName()); + if (null != scenario.getStrategicFormation(campaign)) { + lblForceDesc.setText(campaign.getForce(scenario.getStrategicFormationId()).getFullName()); } else if (scenario instanceof AtBDynamicScenario) { StringBuilder forceBuilder = new StringBuilder(); forceBuilder.append(""); @@ -376,12 +376,12 @@ private void fillStats() { for (ScenarioObjective objective : scenario.getScenarioObjectives()) { objectiveBuilder.append(objective.getDescription()); - objectiveBuilder.append("\n"); + objectiveBuilder.append('\n'); for (String forceName : objective.getAssociatedForceNames()) { - objectiveBuilder.append("\t"); + objectiveBuilder.append('\t'); objectiveBuilder.append(forceName); - objectiveBuilder.append("\n"); + objectiveBuilder.append('\n'); } for (String associatedUnitID : objective.getAssociatedUnitIDs()) { @@ -399,22 +399,22 @@ private void fillStats() { if (associatedUnitName.isBlank()) { continue; } - objectiveBuilder.append("\t"); + objectiveBuilder.append('\t'); objectiveBuilder.append(associatedUnitName); - objectiveBuilder.append("\n"); + objectiveBuilder.append('\n'); } - objectiveBuilder.append("\t"); + objectiveBuilder.append('\t'); objectiveBuilder.append(objective.getTimeLimitString()); - objectiveBuilder.append("\n"); + objectiveBuilder.append('\n'); for (String detail : objective.getDetails()) { - objectiveBuilder.append("\t"); + objectiveBuilder.append('\t'); objectiveBuilder.append(detail); - objectiveBuilder.append("\n"); + objectiveBuilder.append('\n'); } - objectiveBuilder.append("\n"); + objectiveBuilder.append('\n'); } objectiveBuilder.append(scenario.getBattlefieldControlDescription()); diff --git a/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java b/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java index 64f8cd8f22..42b94a2299 100644 --- a/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java +++ b/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java @@ -25,7 +25,7 @@ import mekhq.MekHQ; import mekhq.campaign.Campaign; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; +import mekhq.campaign.force.StrategicFormation; import mekhq.campaign.mission.AtBContract; import mekhq.campaign.mission.enums.AtBLanceRole; import mekhq.campaign.personnel.SkillType; @@ -169,8 +169,8 @@ public Component getTableCellRendererComponent(JTable table, Object value, RowFilter laFilter = new RowFilter<>() { @Override public boolean include(Entry entry) { - Lance l = entry.getModel().getRow(entry.getIdentifier()); - return l.isEligible(campaign); + StrategicFormation strategicFormation = entry.getModel().getRow(entry.getIdentifier()); + return strategicFormation.isEligible(campaign); } }; final NaturalOrderComparator noc = new NaturalOrderComparator(); @@ -223,14 +223,14 @@ public void refresh() { cbContract.addItem(contract); } AtBContract defaultContract = activeContracts.isEmpty() ? null : activeContracts.get(0); - for (Lance l : campaign.getLances().values()) { - if ((l.getContract(campaign) == null) - || !l.getContract(campaign).isActiveOn(campaign.getLocalDate(), true)) { - l.setContract(defaultContract); + for (StrategicFormation strategicFormation : campaign.getStrategicFormations().values()) { + if ((strategicFormation.getContract(campaign) == null) + || !strategicFormation.getContract(campaign).isActiveOn(campaign.getLocalDate(), true)) { + strategicFormation.setContract(defaultContract); } } ((DataTableModel) tblRequiredLances.getModel()).setData(activeContracts); - ((DataTableModel) tblAssignments.getModel()).setData(campaign.getLanceList()); + ((DataTableModel) tblAssignments.getModel()).setData(campaign.getStrategicFormationList()); panRequiredLances.setVisible(tblRequiredLances.getRowCount() > 0); } @@ -341,14 +341,13 @@ public Object getValueAt(int row, int column) { if (COL_CONTRACT == column) { return ((AtBContract) data.get(row)).getName(); } - if (data.get(row) instanceof AtBContract) { - AtBContract contract = (AtBContract) data.get(row); + if (data.get(row) instanceof AtBContract contract) { if (column == COL_TOTAL) { int t = 0; - for (Lance l : campaign.getLanceList()) { - if (data.get(row).equals(l.getContract(campaign)) - && (l.getRole() != AtBLanceRole.UNASSIGNED) - && l.isEligible(campaign)) { + for (StrategicFormation strategicFormation : campaign.getStrategicFormationList()) { + if (data.get(row).equals(strategicFormation.getContract(campaign)) + && (strategicFormation.getRole() != AtBLanceRole.UNASSIGNED) + && strategicFormation.isEligible(campaign)) { t++; } } @@ -358,10 +357,10 @@ public Object getValueAt(int row, int column) { return Integer.toString(contract.getRequiredLances()); } else if (contract.getContractType().getRequiredLanceRole().ordinal() == column - 2) { int t = 0; - for (Lance l : campaign.getLanceList()) { - if (data.get(row).equals(l.getContract(campaign)) - && (l.getRole() == l.getContract(campaign).getContractType().getRequiredLanceRole()) - && l.isEligible(campaign)) { + for (StrategicFormation strategicFormation : campaign.getStrategicFormationList()) { + if (data.get(row).equals(strategicFormation.getContract(campaign)) + && (strategicFormation.getRole() == strategicFormation.getContract(campaign).getContractType().getRequiredLanceRole()) + && strategicFormation.isEligible(campaign)) { t++; } } @@ -402,29 +401,21 @@ public String getColumnName(int column) { } public int getColumnWidth(int col) { - switch (col) { - case COL_FORCE: - case COL_CONTRACT: - return 100; - case COL_WEIGHT_CLASS: - return 5; - default: - return 50; - } + return switch (col) { + case COL_FORCE, COL_CONTRACT -> 100; + case COL_WEIGHT_CLASS -> 5; + default -> 50; + }; } @Override public Class getColumnClass(int c) { - switch (c) { - case COL_FORCE: - return Force.class; - case COL_CONTRACT: - return AtBContract.class; - case COL_ROLE: - return AtBLanceRole.class; - default: - return String.class; - } + return switch (c) { + case COL_FORCE -> Force.class; + case COL_CONTRACT -> AtBContract.class; + case COL_ROLE -> AtBLanceRole.class; + default -> String.class; + }; } @Override @@ -432,8 +423,8 @@ public boolean isCellEditable(int row, int col) { return col > COL_WEIGHT_CLASS; } - public Lance getRow(int row) { - return (Lance) data.get(row); + public StrategicFormation getRow(int row) { + return (StrategicFormation) data.get(row); } @Override @@ -443,27 +434,22 @@ public Object getValueAt(int row, int column) { if (row >= getRowCount()) { return ""; } - switch (column) { - case COL_FORCE: - return campaign.getForce(((Lance) data.get(row)).getForceId()); - case COL_WEIGHT_CLASS: - return WEIGHT_CODES[((Lance) data.get(row)).getWeightClass(campaign)]; - case COL_CONTRACT: - return campaign.getMission(((Lance) data.get(row)).getMissionId()); - case COL_ROLE: - return ((Lance) data.get(row)).getRole(); - default: - return "?"; - } + return switch (column) { + case COL_FORCE -> campaign.getForce(((StrategicFormation) data.get(row)).getForceId()); + case COL_WEIGHT_CLASS -> WEIGHT_CODES[((StrategicFormation) data.get(row)).getWeightClass(campaign)]; + case COL_CONTRACT -> campaign.getMission(((StrategicFormation) data.get(row)).getMissionId()); + case COL_ROLE -> ((StrategicFormation) data.get(row)).getRole(); + default -> "?"; + }; } @Override public void setValueAt(Object value, int row, int col) { if (col == COL_CONTRACT) { - ((Lance) data.get(row)).setContract((AtBContract) value); + ((StrategicFormation) data.get(row)).setContract((AtBContract) value); } else if (col == COL_ROLE) { if (value instanceof AtBLanceRole) { - ((Lance) data.get(row)).setRole((AtBLanceRole) value); + ((StrategicFormation) data.get(row)).setRole((AtBLanceRole) value); } } fireTableDataChanged(); From bc135554a61387914121353c9b38c12bf9c54117 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 25 Nov 2024 16:27:39 -0600 Subject: [PATCH 2/7] Rename `lances` to `strategicFormations` and add force override Renamed the `lances` variable to `strategicFormations` throughout the codebase for clarity. Added functionality to override strategic formation assignment and updated relevant logic to consider this override. Enhanced the strategic formation eligibility check and adjusted UI components to reflect these changes. --- MekHQ/src/mekhq/campaign/Campaign.java | 45 +++++++------ MekHQ/src/mekhq/campaign/force/Force.java | 41 ++++++++++-- .../campaign/force/StrategicFormation.java | 64 +++++++++++++++--- .../mekhq/campaign/io/CampaignXmlParser.java | 25 +++---- .../stratcon/StratconRulesManager.java | 24 ++++--- MekHQ/src/mekhq/gui/ForceRenderer.java | 21 +++--- .../mekhq/gui/adapter/TOEMouseAdapter.java | 65 ++++++++++++++----- .../mekhq/gui/view/LanceAssignmentView.java | 4 +- 8 files changed, 199 insertions(+), 90 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index c1faced120..49952e3221 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -199,7 +199,7 @@ public class Campaign implements ITechManager { // hierarchically structured Force object to define TO&E private Force forces; - private final Hashtable lances; // AtB + private final Hashtable strategicFormations; // AtB private Faction faction; private int techFactionCode; @@ -309,7 +309,7 @@ public Campaign() { setRankSystemDirect(Ranks.getRankSystemFromCode(Ranks.DEFAULT_SYSTEM_CODE)); forces = new Force(name); forceIds.put(0, forces); - lances = new Hashtable<>(); + strategicFormations = new Hashtable<>(); finances = new Finances(); astechPool = 0; medicPool = 0; @@ -449,15 +449,15 @@ public List getAllForces() { } public void importLance(StrategicFormation l) { - lances.put(l.getForceId(), l); + strategicFormations.put(l.getForceId(), l); } public Hashtable getStrategicFormations() { - return lances; + return strategicFormations; } public ArrayList getStrategicFormationList() { - return lances.values().stream() + return strategicFormations.values().stream() .filter(l -> forceIds.containsKey(l.getForceId())) .collect(Collectors.toCollection(ArrayList::new)); } @@ -904,8 +904,8 @@ public void addForce(Force force, Force superForce) { lastForceId = id; if (campaignOptions.isUseAtB() && !force.getUnits().isEmpty()) { - if (null == lances.get(id)) { - lances.put(id, new StrategicFormation(force.getId(), this)); + if (null == strategicFormations.get(id)) { + strategicFormations.put(id, new StrategicFormation(force.getId(), this)); } } @@ -1003,11 +1003,11 @@ public void addUnitToForce(@Nullable Unit u, int id) { if (campaignOptions.isUseAtB()) { if ((null != prevForce) && prevForce.getUnits().isEmpty()) { - lances.remove(prevForce.getId()); + strategicFormations.remove(prevForce.getId()); } - if ((null == lances.get(id)) && (null != force)) { - lances.put(id, new StrategicFormation(force.getId(), this)); + if ((null == strategicFormations.get(id)) && (null != force)) { + strategicFormations.put(id, new StrategicFormation(force.getId(), this)); } } } @@ -1015,10 +1015,9 @@ public void addUnitToForce(@Nullable Unit u, int id) { /** * Adds force and all its subforces to the AtB lance table */ - private void addAllLances(Force force) { - if (!force.getUnits().isEmpty()) { - lances.put(force.getId(), new StrategicFormation(force.getId(), this)); + if (force.isStrategicFormation()) { + strategicFormations.put(force.getId(), new StrategicFormation(force.getId(), this)); } for (Force f : force.getSubForces()) { addAllLances(f); @@ -3618,7 +3617,7 @@ public int getDeploymentDeficit(AtBContract contract) { int role = -Math.max(1, contract.getRequiredLances() / 2); final AtBLanceRole requiredLanceRole = contract.getContractType().getRequiredLanceRole(); - for (StrategicFormation l : lances.values()) { + for (StrategicFormation l : strategicFormations.values()) { if (!l.getRole().isUnassigned() && (l.getMissionId() == contract.getId())) { total++; if (l.getRole() == requiredLanceRole) { @@ -3718,7 +3717,7 @@ && getLocation().getJumpPath().getLastSystem().getId().equals(contract.getSystem for (final AtBScenario s : contract.getCurrentAtBScenarios()) { if ((s.getDate() != null) && s.getDate().equals(getLocalDate())) { int forceId = s.getStrategicFormationId(); - if ((lances.get(forceId) != null) && !forceIds.get(forceId).isDeployed()) { + if ((strategicFormations.get(forceId) != null) && !forceIds.get(forceId).isDeployed()) { // If any unit in the force is under repair, don't deploy the force // Merely removing the unit from deployment would break with user expectation boolean forceUnderRepair = false; @@ -4967,7 +4966,7 @@ public void removeForce(Force force) { } if (campaignOptions.isUseAtB()) { - lances.remove(fid); + strategicFormations.remove(fid); } if (null != force.getParentForce()) { @@ -5020,7 +5019,7 @@ public void removeUnitFromForce(Unit u) { } if (campaignOptions.isUseAtB() && force.getUnits().isEmpty()) { - lances.remove(force.getId()); + strategicFormations.remove(force.getId()); } } } @@ -5595,14 +5594,14 @@ public void writeToXML(final PrintWriter pw) { // CAW: implicit DEPENDS-ON to the node, do not move this above it contractMarket.writeToXML(pw, indent); - if (!lances.isEmpty()) { - MHQXMLUtility.writeSimpleXMLOpenTag(pw, indent++, "lances"); - for (StrategicFormation l : lances.values()) { + if (!strategicFormations.isEmpty()) { + MHQXMLUtility.writeSimpleXMLOpenTag(pw, indent++, "strategicFormations"); + for (StrategicFormation l : strategicFormations.values()) { if (forceIds.containsKey(l.getForceId())) { l.writeToXML(pw, indent); } } - MHQXMLUtility.writeSimpleXMLCloseTag(pw, --indent, "lances"); + MHQXMLUtility.writeSimpleXMLCloseTag(pw, --indent, "strategicFormations"); } MHQXMLUtility.writeSimpleXMLTag(pw, indent, "shipSearchStart", getShipSearchStart()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "shipSearchType", shipSearchType); @@ -6627,8 +6626,8 @@ public TargetRoll getTargetForAcquisition(final IAcquisitionWork acquisition, } public @Nullable AtBContract getAttachedAtBContract(Unit unit) { - if (null != unit && null != lances.get(unit.getForceId())) { - return lances.get(unit.getForceId()).getContract(this); + if (null != unit && null != strategicFormations.get(unit.getForceId())) { + return strategicFormations.get(unit.getForceId()).getContract(this); } return null; } diff --git a/MekHQ/src/mekhq/campaign/force/Force.java b/MekHQ/src/mekhq/campaign/force/Force.java index 8008ab8914..8524b4edf3 100644 --- a/MekHQ/src/mekhq/campaign/force/Force.java +++ b/MekHQ/src/mekhq/campaign/force/Force.java @@ -68,11 +68,17 @@ public class Force { // pathway to force icon public static final int FORCE_NONE = -1; + public static final int STRATEGIC_FORMATION_OVERRIDE_NONE = -1; + public static final int STRATEGIC_FORMATION_OVERRIDE_FALSE = 0; + public static final int STRATEGIC_FORMATION_OVERRIDE_TRUE = 1; + private String name; private StandardForceIcon forceIcon; private Camouflage camouflage; private String desc; private boolean combatForce; + private boolean isStrategicFormation; + private int overrideStrategicFormation; private FormationLevel formationLevel; private FormationLevel overrideFormationLevel; private Force parentForce; @@ -94,6 +100,8 @@ public Force(String name) { setCamouflage(new Camouflage()); setDescription(""); this.combatForce = true; + this.isStrategicFormation = false; + this.overrideStrategicFormation = STRATEGIC_FORMATION_OVERRIDE_NONE; this.formationLevel = FormationLevel.NONE; this.overrideFormationLevel = FormationLevel.NONE; this.parentForce = null; @@ -163,6 +171,22 @@ public void setCombatForce(boolean combatForce, boolean setForSubForces) { } } + public boolean isStrategicFormation() { + return isStrategicFormation; + } + + public void setStrategicFormation(final boolean isStrategicFormation) { + this.isStrategicFormation = isStrategicFormation; + } + + public int getOverrideStrategicFormation() { + return overrideStrategicFormation; + } + + public void setOverrideStrategicFormation(final int overrideStrategicFormation) { + this.overrideStrategicFormation = overrideStrategicFormation; + } + public FormationLevel getFormationLevel() { return formationLevel; } @@ -232,12 +256,18 @@ public boolean isDeployed() { public List getAllParents() { List parentForces = new ArrayList<>(); - Force parentForce = getParentForce(); + Force parentFormation = parentForce; - while (parentForce.getParentForce() != null) { - parentForces.add(parentForce.getParentForce()); + if (parentForce != null) { + parentForces.add(parentForce); + } + + while (parentFormation != null) { + parentFormation = parentFormation.getParentForce(); - parentForce = parentForce.getParentForce(); + if (parentFormation != null) { + parentForces.add(parentFormation); + } } return parentForces; @@ -653,6 +683,7 @@ public void writeToXML(PrintWriter pw1, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "desc", desc); } MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "combatForce", combatForce); + MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "overrideStrategicFormation", overrideStrategicFormation); MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "formationLevel", formationLevel.toString()); MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "populateOriginNode", overrideFormationLevel.toString()); MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "scenarioId", scenarioId); @@ -700,6 +731,8 @@ public void writeToXML(PrintWriter pw1, int indent) { retVal.setDescription(wn2.getTextContent().trim()); } else if (wn2.getNodeName().equalsIgnoreCase("combatForce")) { retVal.setCombatForce(Boolean.parseBoolean(wn2.getTextContent().trim()), false); + } else if (wn2.getNodeName().equalsIgnoreCase("overrideStrategicFormation")) { + retVal.setOverrideStrategicFormation(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("formationLevel")) { retVal.setFormationLevel(FormationLevel.parseFromString(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("populateOriginNode")) { diff --git a/MekHQ/src/mekhq/campaign/force/StrategicFormation.java b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java index 3b2c485f47..f1825c1071 100644 --- a/MekHQ/src/mekhq/campaign/force/StrategicFormation.java +++ b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java @@ -39,10 +39,13 @@ import java.io.PrintWriter; import java.time.LocalDate; -import java.util.ArrayList; import java.util.List; import java.util.UUID; +import static megamek.common.EntityWeightClass.WEIGHT_ULTRA_LIGHT; +import static mekhq.campaign.force.Force.STRATEGIC_FORMATION_OVERRIDE_NONE; +import static mekhq.campaign.force.Force.STRATEGIC_FORMATION_OVERRIDE_TRUE; + /** * Used by Against the Bot & StratCon to track additional information about each force * on the TO&E that has at least one unit assigned. Extra info includes whether @@ -206,9 +209,30 @@ public int getWeightClass(Campaign campaign) { */ double weight = calculateTotalWeight(campaign, forceId); + Force originForce = campaign.getForce(forceId); + + if (originForce == null) { + return WEIGHT_ULTRA_LIGHT; + } + + List subForces = originForce.getSubForces(); + int subForcesCount = subForces.size(); + + for (Force childForce : subForces) { + double childForceWeight = calculateTotalWeight(campaign, childForce.getId()); + + if (childForceWeight > 0) { + weight += childForceWeight; + } else { + subForcesCount--; + } + } + + weight = weight / subForcesCount; + weight = weight * 4.0 / getStdLanceSize(campaign.getFaction()); if (weight < 40) { - return EntityWeightClass.WEIGHT_ULTRA_LIGHT; + return WEIGHT_ULTRA_LIGHT; } if (weight <= 130) { return EntityWeightClass.WEIGHT_LIGHT; @@ -229,7 +253,12 @@ public boolean isEligible(Campaign campaign) { // ensure the lance is marked as a combat force final Force force = campaign.getForce(forceId); - if ((force == null) || !force.isCombatForce()) { + if (force == null) { + return false; + } + + if (!force.isCombatForce()) { + force.setStrategicFormation(false); return false; } @@ -241,12 +270,14 @@ public boolean isEligible(Campaign campaign) { int size = getSize(campaign); if (size < getStdLanceSize(campaign.getFaction()) - 1 || size > getStdLanceSize(campaign.getFaction()) + 2) { + force.setStrategicFormation(false); return false; } } if (campaign.getCampaignOptions().isLimitLanceWeight() && getWeightClass(campaign) > EntityWeightClass.WEIGHT_ASSAULT) { + force.setStrategicFormation(false); return false; } @@ -258,6 +289,7 @@ size > getStdLanceSize(campaign.getFaction()) + 2) { if (entity != null) { if (entity.getUnitType() >= UnitType.JUMPSHIP) { + force.setStrategicFormation(false); return false; } if ((entity.getEntityType() & ETYPE_GROUND) != 0) { @@ -267,19 +299,28 @@ size > getStdLanceSize(campaign.getFaction()) + 2) { } } - if (hasGround) { - ArrayList strategicFormations = campaign.getStrategicFormationList(); - List allLanceForceIds = new ArrayList<>(); + int isOverridden = force.getOverrideStrategicFormation(); + if (isOverridden != STRATEGIC_FORMATION_OVERRIDE_NONE) { + boolean overrideState = isOverridden == STRATEGIC_FORMATION_OVERRIDE_TRUE; + force.setStrategicFormation(overrideState); + + List associatedForces = force.getAllParents(); + associatedForces.addAll(force.getAllSubForces()); - for (StrategicFormation strategicFormation : strategicFormations) { - allLanceForceIds.add(strategicFormation.getForceId()); + for (Force associatedForce : associatedForces) { + associatedForce.setStrategicFormation(false); } + return overrideState; + } + + if (hasGround) { // Parent Forces List parentForces = force.getAllParents(); for (Force parentForce : parentForces) { - if (allLanceForceIds.contains(parentForce.getId())) { + if (parentForce.isStrategicFormation()) { + force.setStrategicFormation(false); return false; } } @@ -288,12 +329,15 @@ size > getStdLanceSize(campaign.getFaction()) + 2) { List childForces = force.getAllSubForces(); for (Force childForce : childForces) { - if (allLanceForceIds.contains(childForce.getId())) { + if (childForce.isStrategicFormation()) { + force.setStrategicFormation(false); return false; } } } + force.setStrategicFormation(hasGround); + return hasGround; } diff --git a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java index fdd374c545..65ae61482f 100644 --- a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java +++ b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java @@ -279,8 +279,8 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { retVal.setUnitMarket(retVal.getCampaignOptions().getUnitMarketMethod().getUnitMarket()); retVal.getUnitMarket().fillFromXML(wn, retVal, version); foundUnitMarket = true; - } else if (xn.equalsIgnoreCase("lances")) { - processLanceNodes(retVal, wn); + } else if (xn.equalsIgnoreCase("lances") || xn.equalsIgnoreCase("strategicFormations")) { + processStrategicFormationNodes(retVal, wn); } else if (xn.equalsIgnoreCase("retirementDefectionTracker")) { retVal.setRetirementDefectionTracker( RetirementDefectionTracker.generateInstanceFromXML(wn, retVal)); @@ -759,29 +759,30 @@ private static void processInfoNode(Campaign retVal, Node wni, Version version) retVal.setNewReports(newReports); } - private static void processLanceNodes(Campaign retVal, Node wn) { - NodeList wList = wn.getChildNodes(); + private static void processStrategicFormationNodes(Campaign campaign, Node workingNode) { + NodeList workingNodes = workingNode.getChildNodes(); - // Okay, lets iterate through the children, eh? - for (int x = 0; x < wList.getLength(); x++) { - Node wn2 = wList.item(x); + // Okay, let's iterate through the children, eh? + for (int x = 0; x < workingNodes.getLength(); x++) { + Node wn2 = workingNodes.item(x); // If it's not an element node, we ignore it. if (wn2.getNodeType() != Node.ELEMENT_NODE) { continue; } - if (!wn2.getNodeName().equalsIgnoreCase("lance")) { + if (!wn2.getNodeName().equalsIgnoreCase("lance") + && !wn2.getNodeName().equalsIgnoreCase("strategicFormations")) { // Error condition of sorts! // Errr, what should we do here? - logger.error("Unknown node type not loaded in Lance nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in strategicFormations nodes: " + wn2.getNodeName()); continue; } - StrategicFormation l = StrategicFormation.generateInstanceFromXML(wn2); + StrategicFormation strategicFormation = StrategicFormation.generateInstanceFromXML(wn2); - if (l != null) { - retVal.importLance(l); + if (strategicFormation != null) { + campaign.importLance(strategicFormation); } } } diff --git a/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java b/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java index 7d63ffb606..2d2393b148 100644 --- a/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java +++ b/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java @@ -1427,48 +1427,52 @@ public static List getAvailableForceIDs(Campaign campaign) { /** * This is a list of all force IDs for forces that can be deployed to a scenario - * in the given force - * template a) have not been assigned to a track b) are combat-capable c) are - * not deployed to a - * scenario d) if attempting to deploy as reinforcements, haven't already failed + * in the given force template a) have not been assigned to a track b) are combat-capable c) are + * not deployed to a scenario d) if attempting to deploy as reinforcements, haven't already failed * to deploy */ public static List getAvailableForceIDs(int unitType, Campaign campaign, StratconTrackState currentTrack, boolean reinforcements, @Nullable StratconScenario currentScenario, StratconCampaignState campaignState) { List retVal = new ArrayList<>(); - // assemble a set of all force IDs that are currently assigned to tracks that - // are not this one + // assemble a set of all force IDs that are currently assigned to tracks that are not this one Set forcesInTracks = campaign.getActiveAtBContracts().stream() .flatMap(contract -> contract.getStratconCampaignState().getTracks().stream()) .filter(track -> (track != currentTrack) || !reinforcements) .flatMap(track -> track.getAssignedForceCoords().keySet().stream()) .collect(Collectors.toSet()); - // if there's an existing scenario and we're doing reinforcements, + // if there's an existing scenario, and we're doing reinforcements, // prevent forces that failed to deploy from trying to deploy again if (reinforcements && (currentScenario != null)) { forcesInTracks.addAll(currentScenario.getFailedReinforcements()); } - for (int key : campaign.getStrategicFormations().keySet()) { - Force force = campaign.getForce(key); + for (StrategicFormation formation : campaign.getStrategicFormations().values()) { + if (!formation.isEligible(campaign)) { + continue; + } + + Force force = campaign.getForce(formation.getForceId()); if (force == null) { continue; } + logger.info(force.getName()); + int primaryUnitType = force.getPrimaryUnitType(campaign); boolean noReinforcementRestriction = !reinforcements || (reinforcements && (getReinforcementType(force.getId(), currentTrack, campaign, campaignState) != ReinforcementEligibilityType.None)); - if ((force.getScenarioId() <= 0) && !force.getUnits().isEmpty() + if ((force.getScenarioId() <= 0) && !force.getAllUnits(true).isEmpty() && !forcesInTracks.contains(force.getId()) && forceCompositionMatchesDeclaredUnitType(primaryUnitType, unitType, reinforcements) && noReinforcementRestriction && !subElementsOrSelfDeployed(force, campaign)) { retVal.add(force.getId()); } + retVal.add(force.getId()); } return retVal; diff --git a/MekHQ/src/mekhq/gui/ForceRenderer.java b/MekHQ/src/mekhq/gui/ForceRenderer.java index 236d718440..4e0e86ba07 100644 --- a/MekHQ/src/mekhq/gui/ForceRenderer.java +++ b/MekHQ/src/mekhq/gui/ForceRenderer.java @@ -18,13 +18,6 @@ */ package mekhq.gui; -import java.awt.Component; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JTree; -import javax.swing.tree.DefaultTreeCellRenderer; - import megamek.client.ui.Messages; import megamek.common.Entity; import megamek.common.GunEmplacement; @@ -35,6 +28,10 @@ import mekhq.campaign.unit.Unit; import mekhq.utilities.ReportingUtilities; +import javax.swing.*; +import javax.swing.tree.DefaultTreeCellRenderer; +import java.awt.*; + public class ForceRenderer extends DefaultTreeCellRenderer { private static final MMLogger logger = MMLogger.create(ForceRenderer.class); @@ -51,7 +48,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); setOpaque(false); - if (value instanceof Unit) { + if (value instanceof Unit unit) { String name = ReportingUtilities.messageSurroundedBySpanWithColor( MekHQ.getMHQOptions().getFontColorNegativeHexColor(), "No Crew"); if (((Unit) value).getEntity() instanceof GunEmplacement) { @@ -59,7 +56,6 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean } String c3network = ""; StringBuilder transport = new StringBuilder(); - Unit unit = (Unit) value; Person person = unit.getCommander(); if (person != null) { name = person.getFullTitle(); @@ -142,8 +138,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean setBackground(MekHQ.getMHQOptions().getDeployedBackground()); setOpaque(true); } - } else if (value instanceof Force) { - Force force = (Force) value; + } else if (value instanceof Force force) { getAccessibleContext().setAccessibleName(( force.isDeployed() ? "Deployed Force: " : "Force: ") + force.getFullName()); if (!sel && force.isDeployed()) { @@ -151,6 +146,10 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean setBackground(MekHQ.getMHQOptions().getDeployedBackground()); setOpaque(true); } + + if (force.isStrategicFormation()) { + setText("" + force.getName() + ""); + } } else { logger.error("Attempted to render node with unknown node class of " + ((value != null) ? value.getClass() : "null")); diff --git a/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java index fae28bb097..3a55420aed 100644 --- a/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java @@ -18,24 +18,6 @@ */ package mekhq.gui.adapter; -import java.awt.event.ActionEvent; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.StringJoiner; -import java.util.StringTokenizer; -import java.util.UUID; -import java.util.Vector; - -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.JTree; -import javax.swing.tree.TreePath; - import megamek.client.ui.dialogs.CamoChooserDialog; import megamek.common.EntityWeightClass; import megamek.common.GunEmplacement; @@ -68,6 +50,15 @@ import mekhq.gui.utilities.JMenuHelpers; import mekhq.gui.utilities.StaticChecks; +import javax.swing.*; +import javax.swing.tree.TreePath; +import java.awt.event.ActionEvent; +import java.util.*; + +import static mekhq.campaign.force.Force.STRATEGIC_FORMATION_OVERRIDE_FALSE; +import static mekhq.campaign.force.Force.STRATEGIC_FORMATION_OVERRIDE_NONE; +import static mekhq.campaign.force.Force.STRATEGIC_FORMATION_OVERRIDE_TRUE; + public class TOEMouseAdapter extends JPopupMenuAdapter { private static final MMLogger logger = MMLogger.create(TOEMouseAdapter.class); @@ -136,6 +127,8 @@ public static void connect(CampaignGUI gui, JTree tree) { private static final String CHANGE_NAME = "CHANGE_NAME"; private static final String CHANGE_COMBAT_STATUS = "CHANGE_COMBAT_STATUS"; private static final String CHANGE_COMBAT_STATUSES = "CHANGE_COMBAT_STATUSES"; + private static final String CHANGE_STRATEGIC_FORCE_OVERRIDE = "CHANGE_STRATEGIC_FORCE_OVERRIDE"; + private static final String REMOVE_STRATEGIC_FORCE_OVERRIDE = "REMOVE_STRATEGIC_FORCE_OVERRIDE"; private static final String COMMAND_CHANGE_FORCE_CAMO = "CHANGE_CAMO|FORCE|empty|"; private static final String COMMAND_CHANGE_FORCE_DESC = "CHANGE_DESC|FORCE|empty|"; @@ -146,6 +139,8 @@ public static void connect(CampaignGUI gui, JTree tree) { private static final String COMMAND_CHANGE_FORCE_NAME = "CHANGE_NAME|FORCE|empty|"; private static final String COMMAND_CHANGE_FORCE_COMBAT_STATUS = "CHANGE_COMBAT_STATUS|FORCE|empty|"; private static final String COMMAND_CHANGE_FORCE_COMBAT_STATUSES = "CHANGE_COMBAT_STATUSES|FORCE|empty|"; + private static final String COMMAND_CHANGE_STRATEGIC_FORCE_OVERRIDE = "CHANGE_STRATEGIC_FORCE_OVERRIDE|FORCE|empty|"; + private static final String COMMAND_REMOVE_STRATEGIC_FORCE_OVERRIDE = "REMOVE_STRATEGIC_FORCE_OVERRIDE|FORCE|empty|"; private static final String COMMAND_OVERRIDE_FORCE_FORMATION_LEVEL = "OVERRIDE_FORMATION_LEVEL|FORCE|FORMATION_LEVEL|"; @@ -443,6 +438,28 @@ public void actionPerformed(ActionEvent action) { } gui.undeployForces(forces); gui.getTOETab().refreshForceView(); + } else if (command.contains(CHANGE_STRATEGIC_FORCE_OVERRIDE)) { + if (singleForce == null) { + return; + } + + boolean overrideState = singleForce.getOverrideStrategicFormation() == STRATEGIC_FORMATION_OVERRIDE_TRUE; + singleForce.setStrategicFormation(!overrideState); + singleForce.setOverrideStrategicFormation(!overrideState ? STRATEGIC_FORMATION_OVERRIDE_TRUE : STRATEGIC_FORMATION_OVERRIDE_FALSE); + + for (Force formation : gui.getCampaign().getAllForces()) { + MekHQ.triggerEvent(new OrganizationChangedEvent(formation)); + } + } else if (command.contains(REMOVE_STRATEGIC_FORCE_OVERRIDE)) { + if (singleForce == null) { + return; + } + + singleForce.setOverrideStrategicFormation(STRATEGIC_FORMATION_OVERRIDE_NONE); + + for (Force formation : gui.getCampaign().getAllForces()) { + MekHQ.triggerEvent(new OrganizationChangedEvent(formation)); + } } else if (command.contains(TOEMouseAdapter.REMOVE_FORCE)) { for (Force force : forces) { if (null != force && null != force.getParentForce()) { @@ -1031,6 +1048,18 @@ protected Optional createPopupMenu() { menuItem.addActionListener(this); popup.add(menuItem); + JMenuItem optionStrategicForceOverride = new JMenuItem(force.isStrategicFormation() ? + "Remove Strategic Formation Assignment" : "Assign as Strategic Formation"); + optionStrategicForceOverride.setActionCommand(COMMAND_CHANGE_STRATEGIC_FORCE_OVERRIDE + forceIds); + optionStrategicForceOverride.addActionListener(this); + popup.add(optionStrategicForceOverride); + + JMenuItem optionRemoveStrategicForceOverride = new JMenuItem("Remove Strategic Force Override"); + optionRemoveStrategicForceOverride.setActionCommand(COMMAND_REMOVE_STRATEGIC_FORCE_OVERRIDE + forceIds); + optionRemoveStrategicForceOverride.addActionListener(this); + optionRemoveStrategicForceOverride.setVisible(force.getOverrideStrategicFormation() != STRATEGIC_FORMATION_OVERRIDE_NONE); + popup.add(optionRemoveStrategicForceOverride); + if (StaticChecks.areAllForcesUndeployed(gui.getCampaign(), forces) && StaticChecks.areAllCombatForces(forces)) { menu = new JMenu("Deploy Force"); diff --git a/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java b/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java index 42b94a2299..32f05ff63c 100644 --- a/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java +++ b/MekHQ/src/mekhq/gui/view/LanceAssignmentView.java @@ -387,7 +387,7 @@ class LanceAssignmentTableModel extends DataTableModel { public LanceAssignmentTableModel(Campaign campaign) { this.campaign = campaign; data = new ArrayList<>(); - columnNames = new String[]{"Force", "Wt", "Mission", "Role"}; + columnNames = new String[]{"Force", "Weight Class", "Mission", "Role"}; } @Override @@ -429,7 +429,7 @@ public StrategicFormation getRow(int row) { @Override public Object getValueAt(int row, int column) { - final String[] WEIGHT_CODES = {"UL", "L", "M", "H", "A", "SH"}; + final String[] WEIGHT_CODES = {"Ultra-Light", "Light", "Medium", "Heavy", "Assault", "Super Heavy"}; if (row >= getRowCount()) { return ""; From 5b00e18b4326996a8d8538e9cfd7524e1cb71a1a Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 25 Nov 2024 16:37:35 -0600 Subject: [PATCH 3/7] Refactored force rendering logic in ForceRenderer.java Consolidated text formatting into a single String based on formation status. Improved readability and maintainability by reducing repetitive code. --- MekHQ/src/mekhq/gui/ForceRenderer.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/MekHQ/src/mekhq/gui/ForceRenderer.java b/MekHQ/src/mekhq/gui/ForceRenderer.java index 4e0e86ba07..acecca9f71 100644 --- a/MekHQ/src/mekhq/gui/ForceRenderer.java +++ b/MekHQ/src/mekhq/gui/ForceRenderer.java @@ -32,6 +32,8 @@ import javax.swing.tree.DefaultTreeCellRenderer; import java.awt.*; +import static mekhq.campaign.force.Force.STRATEGIC_FORMATION_OVERRIDE_NONE; + public class ForceRenderer extends DefaultTreeCellRenderer { private static final MMLogger logger = MMLogger.create(ForceRenderer.class); @@ -147,9 +149,16 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean setOpaque(true); } + String format; if (force.isStrategicFormation()) { - setText("" + force.getName() + ""); + format = (force.getOverrideStrategicFormation() != STRATEGIC_FORMATION_OVERRIDE_NONE) ? + "%s" : "%s"; + } else { + format = (force.getOverrideStrategicFormation() != STRATEGIC_FORMATION_OVERRIDE_NONE) ? + "%s" : "%s"; } + + setText(String.format(format, force.getName())); } else { logger.error("Attempted to render node with unknown node class of " + ((value != null) ? value.getClass() : "null")); From 5cf9b56c37b85cbd800e5d4a8c6f53a3802cc54d Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 25 Nov 2024 16:54:26 -0600 Subject: [PATCH 4/7] Remove redundant logging and simplify condition handling Removed an unnecessary log statement that printed the force name. Simplified the conditional check for reinforcement restrictions, ensuring better readability and maintainability. --- .../stratcon/StratconRulesManager.java | 21 +++++++++---------- .../mekhq/gui/adapter/TOEMouseAdapter.java | 14 ++++++++----- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java b/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java index 2d2393b148..47a4e44edd 100644 --- a/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java +++ b/MekHQ/src/mekhq/campaign/stratcon/StratconRulesManager.java @@ -1459,20 +1459,19 @@ public static List getAvailableForceIDs(int unitType, Campaign campaign continue; } - logger.info(force.getName()); - int primaryUnitType = force.getPrimaryUnitType(campaign); - boolean noReinforcementRestriction = !reinforcements || (reinforcements - && (getReinforcementType(force.getId(), currentTrack, campaign, - campaignState) != ReinforcementEligibilityType.None)); - if ((force.getScenarioId() <= 0) && !force.getAllUnits(true).isEmpty() - && !forcesInTracks.contains(force.getId()) - && forceCompositionMatchesDeclaredUnitType(primaryUnitType, unitType, reinforcements) - && noReinforcementRestriction - && !subElementsOrSelfDeployed(force, campaign)) { + boolean noReinforcementRestriction = !reinforcements || + (getReinforcementType(force.getId(), currentTrack, campaign, campaignState) != ReinforcementEligibilityType.None); + + if ((force.getScenarioId() <= 0) + && !force.getAllUnits(true).isEmpty() + && !forcesInTracks.contains(force.getId()) + && forceCompositionMatchesDeclaredUnitType(primaryUnitType, unitType, reinforcements) + && noReinforcementRestriction + && !subElementsOrSelfDeployed(force, campaign)) { + retVal.add(force.getId()); } - retVal.add(force.getId()); } return retVal; diff --git a/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java index 3a55420aed..c1602fabc3 100644 --- a/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java @@ -438,14 +438,18 @@ public void actionPerformed(ActionEvent action) { } gui.undeployForces(forces); gui.getTOETab().refreshForceView(); + + for (Force formation : gui.getCampaign().getAllForces()) { + MekHQ.triggerEvent(new OrganizationChangedEvent(formation)); + } } else if (command.contains(CHANGE_STRATEGIC_FORCE_OVERRIDE)) { if (singleForce == null) { return; } - boolean overrideState = singleForce.getOverrideStrategicFormation() == STRATEGIC_FORMATION_OVERRIDE_TRUE; - singleForce.setStrategicFormation(!overrideState); - singleForce.setOverrideStrategicFormation(!overrideState ? STRATEGIC_FORMATION_OVERRIDE_TRUE : STRATEGIC_FORMATION_OVERRIDE_FALSE); + boolean formationState = singleForce.isStrategicFormation(); + singleForce.setStrategicFormation(!formationState); + singleForce.setOverrideStrategicFormation(!formationState ? STRATEGIC_FORMATION_OVERRIDE_TRUE : STRATEGIC_FORMATION_OVERRIDE_FALSE); for (Force formation : gui.getCampaign().getAllForces()) { MekHQ.triggerEvent(new OrganizationChangedEvent(formation)); @@ -1048,8 +1052,8 @@ protected Optional createPopupMenu() { menuItem.addActionListener(this); popup.add(menuItem); - JMenuItem optionStrategicForceOverride = new JMenuItem(force.isStrategicFormation() ? - "Remove Strategic Formation Assignment" : "Assign as Strategic Formation"); + JMenuItem optionStrategicForceOverride = new JMenuItem((force.isStrategicFormation() ? + "Never" : "Always") + " Consider Force a Strategic Formation"); optionStrategicForceOverride.setActionCommand(COMMAND_CHANGE_STRATEGIC_FORCE_OVERRIDE + forceIds); optionStrategicForceOverride.addActionListener(this); popup.add(optionStrategicForceOverride); From c084b105e2eb086f3c1863c83cdac94b234b487e Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 25 Nov 2024 16:59:19 -0600 Subject: [PATCH 5/7] Fix HTML entities and update parameter name Replaced '&' with '&' to properly encode HTML entities in comments. Additionally, renamed the 'c' parameter to 'campaign' for clarity and consistency. --- MekHQ/src/mekhq/campaign/force/StrategicFormation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/force/StrategicFormation.java b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java index f1825c1071..43005fa41e 100644 --- a/MekHQ/src/mekhq/campaign/force/StrategicFormation.java +++ b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java @@ -47,7 +47,7 @@ import static mekhq.campaign.force.Force.STRATEGIC_FORMATION_OVERRIDE_TRUE; /** - * Used by Against the Bot & StratCon to track additional information about each force + * Used by Against the Bot & StratCon to track additional information about each force * on the TO&E that has at least one unit assigned. Extra info includes whether * the force counts as a Strategic Formation eligible for assignment to a scenario role * and what the assignment is on which contract. @@ -576,7 +576,7 @@ public static StrategicFormation generateInstanceFromXML(Node wn) { /** * Worker function that calculates the total weight of a force with the given ID * - * @param c Campaign in which the force resides + * @param campaign Campaign in which the force resides * @param forceId Force for which to calculate weight * @return Total force weight */ From e77666ad25e27fe6982a2836a801f25acee3f64e Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 25 Nov 2024 17:03:58 -0600 Subject: [PATCH 6/7] Refactored StrategicFormation to remove redundant parent checks Removed the redundant check for parent forces being strategic formations. This simplification improves code readability and potentially enhances performance by eliminating unnecessary iterations. --- .../src/mekhq/campaign/force/StrategicFormation.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/force/StrategicFormation.java b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java index 43005fa41e..8efcd7df7c 100644 --- a/MekHQ/src/mekhq/campaign/force/StrategicFormation.java +++ b/MekHQ/src/mekhq/campaign/force/StrategicFormation.java @@ -315,17 +315,6 @@ size > getStdLanceSize(campaign.getFaction()) + 2) { } if (hasGround) { - // Parent Forces - List parentForces = force.getAllParents(); - - for (Force parentForce : parentForces) { - if (parentForce.isStrategicFormation()) { - force.setStrategicFormation(false); - return false; - } - } - - // Child Forces List childForces = force.getAllSubForces(); for (Force childForce : childForces) { From d1b53f6496906ccfb22b27eb327e300285931bc5 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Fri, 29 Nov 2024 14:07:30 -0600 Subject: [PATCH 7/7] Post-merge corrections --- MekHQ/src/mekhq/AtBGameThread.java | 48 +++++++++++------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/MekHQ/src/mekhq/AtBGameThread.java b/MekHQ/src/mekhq/AtBGameThread.java index 42281703fe..a7e6103dec 100644 --- a/MekHQ/src/mekhq/AtBGameThread.java +++ b/MekHQ/src/mekhq/AtBGameThread.java @@ -18,47 +18,33 @@ */ package mekhq; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - -import javax.swing.JOptionPane; - import io.sentry.Sentry; import megamek.client.AbstractClient; import megamek.client.Client; import megamek.client.bot.BotClient; +import megamek.client.bot.princess.BehaviorSettings; import megamek.client.bot.princess.Princess; +import megamek.client.bot.princess.PrincessException; import megamek.client.generator.RandomCallsignGenerator; import megamek.client.ui.swing.ClientGUI; -import megamek.common.Entity; -import megamek.common.IAero; -import megamek.common.Infantry; -import megamek.common.MapSettings; -import megamek.common.Minefield; -import megamek.common.UnitType; +import megamek.common.*; +import megamek.common.annotations.Nullable; import megamek.common.planetaryconditions.PlanetaryConditions; import megamek.logging.MMLogger; import mekhq.campaign.force.Force; -import mekhq.campaign.force.Lance; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBDynamicScenario; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.BotForce; -import mekhq.campaign.mission.Scenario; +import mekhq.campaign.force.StrategicFormation; +import mekhq.campaign.mission.*; import mekhq.campaign.personnel.Person; import mekhq.campaign.unit.Unit; +import javax.swing.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.*; +import java.util.stream.Collectors; + /** * Enhanced version of GameThread which imports settings and non-player units * into the MM game @@ -621,7 +607,7 @@ protected List setupBotEntities(BotClient botClient, BotForce botForce, lanceSize = StrategicFormation.getStdLanceSize(contract.getEmployerFaction()); } - Comparator comp = Comparator.comparing(((Entity entity) -> entity.getEntityMajorTypeName(e.getEntityType()))); + Comparator comp = Comparator.comparing(((Entity e) -> Entity.getEntityMajorTypeName(e.getEntityType()))); comp = comp.thenComparing(((Entity e) -> e.getRunMP()), Comparator.reverseOrder()); comp = comp.thenComparing(((Entity e) -> e.getRole().toString())); entitiesSorted.sort(comp); @@ -632,13 +618,13 @@ protected List setupBotEntities(BotClient botClient, BotForce botForce, } if ((i != 0) - && !lastType.equals(entity.getEntityMajorTypeName(entity.getEntityType()))) { + && !lastType.equals(Entity.getEntityMajorTypeName(entity.getEntityType()))) { forceIdLance++; lanceName = RCG.generate(); i = forceIdLance * lanceSize; } - lastType = entity.getEntityMajorTypeName(entity.getEntityType()); + lastType = Entity.getEntityMajorTypeName(entity.getEntityType()); entity.setOwner(botClient.getLocalPlayer()); String fName = String.format(forceName, lanceName, forceIdLance); entity.setForceString(fName);