|
32 | 32 | */ |
33 | 33 | package mekhq.campaign.mission; |
34 | 34 |
|
| 35 | +import static java.lang.Math.floor; |
35 | 36 | import static java.lang.Math.max; |
36 | 37 | import static java.lang.Math.min; |
37 | 38 | import static java.lang.Math.round; |
|
111 | 112 | import mekhq.campaign.Hangar; |
112 | 113 | import mekhq.campaign.againstTheBot.AtBConfiguration; |
113 | 114 | import mekhq.campaign.camOpsReputation.IUnitRating; |
| 115 | +import mekhq.campaign.campaignOptions.BoardScalingType; |
114 | 116 | import mekhq.campaign.campaignOptions.CampaignOptions; |
115 | | -import mekhq.campaign.force.CombatTeam; |
116 | 117 | import mekhq.campaign.enums.DragoonRating; |
| 118 | +import mekhq.campaign.force.CombatTeam; |
117 | 119 | import mekhq.campaign.force.Force; |
118 | 120 | import mekhq.campaign.mission.AtBDynamicScenario.BenchedEntityData; |
119 | 121 | import mekhq.campaign.mission.ScenarioForceTemplate.ForceAlignment; |
@@ -280,7 +282,7 @@ public static void finalizeScenario(AtBDynamicScenario scenario, AtBContract con |
280 | 282 |
|
281 | 283 | // approximate estimate, anyway. |
282 | 284 | scenario.setForceCount(generatedLanceCount + (playerForceUnitCount / 4)); |
283 | | - setScenarioMapSize(scenario); |
| 285 | + setScenarioMapSize(scenario, campaign); |
284 | 286 | scenario.setScenarioMap(campaign.getCampaignOptions().getFixedMapChance()); |
285 | 287 | setDeploymentZones(scenario); |
286 | 288 | setDestinationZones(scenario); |
@@ -1872,57 +1874,83 @@ private static void setPlanetaryConditions(AtBDynamicScenario scenario, AtBContr |
1872 | 1874 | } |
1873 | 1875 |
|
1874 | 1876 | /** |
1875 | | - * Sets dynamic AtB-sized base map size for the given scenario. |
| 1877 | + * Calculates and sets the dimensions of the scenario map based on the forces involved and the scenario template |
| 1878 | + * parameters. |
1876 | 1879 | * |
1877 | | - * @param scenario The scenario to process. |
| 1880 | + * <p>This method determines the map size using one of two strategies defined in the {@code ScenarioTemplate}: |
| 1881 | + * <ul> |
| 1882 | + * <li><b>Standard AtB Sizing:</b> If enabled, the size is calculated based on the total unit count (player + |
| 1883 | + * bot forces). It follows the "Total Warfare" suggestion of roughly one map sheet per 4 units. Infantry |
| 1884 | + * units in bot forces are excluded from this count to prevent excessive map sizes. |
| 1885 | + * </li> |
| 1886 | + * <li><b>Template Base Sizing:</b> Uses fixed base dimensions defined in the template, optionally scaled by |
| 1887 | + * increments based on the number of forces involved. |
| 1888 | + * </li> |
| 1889 | + * </ul> |
| 1890 | + * |
| 1891 | + * <p>Additionally, if the template allows rotation, there is a 50% chance the calculated X and Y dimensions |
| 1892 | + * will be swapped.</p> |
| 1893 | + * |
| 1894 | + * @param scenario The dynamic scenario object to update with the new map dimensions. |
| 1895 | + * @param campaign The current campaign context, used to retrieve unit counts and entity lists. |
1878 | 1896 | */ |
1879 | | - public static void setScenarioMapSize(AtBDynamicScenario scenario) { |
| 1897 | + public static void setScenarioMapSize(AtBDynamicScenario scenario, Campaign campaign) { |
1880 | 1898 | int mapSizeX; |
1881 | 1899 | int mapSizeY; |
1882 | 1900 | ScenarioTemplate template = scenario.getTemplate(); |
1883 | | - |
1884 | | - // if the template says to use standard AtB sizing, determine it randomly here |
1885 | | - if (template.mapParameters.isUseStandardAtBSizing()) { |
1886 | | - int roll = randomInt(20) + 1; |
1887 | | - if (roll < 6) { |
1888 | | - mapSizeX = 20; |
1889 | | - mapSizeY = 10; |
1890 | | - } else if (roll < 11) { |
1891 | | - mapSizeX = 10; |
1892 | | - mapSizeY = 20; |
1893 | | - } else if (roll < 13) { |
1894 | | - mapSizeX = 30; |
1895 | | - mapSizeY = 10; |
1896 | | - } else if (roll < 15) { |
1897 | | - mapSizeX = 10; |
1898 | | - mapSizeY = 30; |
1899 | | - } else if (roll < 19) { |
1900 | | - mapSizeX = 20; |
1901 | | - mapSizeY = 20; |
1902 | | - } else if (roll == 19) { |
1903 | | - mapSizeX = 40; |
1904 | | - mapSizeY = 10; |
1905 | | - } else { |
1906 | | - mapSizeX = 10; |
1907 | | - mapSizeY = 40; |
| 1901 | + ScenarioMapParameters mapParameters = template.mapParameters; |
| 1902 | + if (mapParameters.isUseStandardAtBSizing()) { |
| 1903 | + CampaignOptions campaignOptions = campaign.getCampaignOptions(); |
| 1904 | + BoardScalingType boardScaling = campaignOptions.getBoardScalingType(); |
| 1905 | + int heightModifier = boardScaling.getHeightModifier(); |
| 1906 | + int minimumWidth = boardScaling.getMinimumWidth(); |
| 1907 | + |
| 1908 | + // We're using this as a shortcut, rather than fetching the player force directly |
| 1909 | + int unitCount = getUnitCountWithoutUsingASeedForce(campaign); |
| 1910 | + for (BotForce botForce : scenario.getBotForces()) { |
| 1911 | + for (Entity entity : botForce.getFullEntityList(campaign)) { |
| 1912 | + // We don't count infantry (on the OpFor side) to avoid large infantry fights generating massive |
| 1913 | + // scenario maps |
| 1914 | + if (!entity.isInfantry()) { |
| 1915 | + unitCount++; |
| 1916 | + } |
| 1917 | + } |
1908 | 1918 | } |
1909 | | - // otherwise, the map width/height have been specified explicitly |
| 1919 | + |
| 1920 | + int mapSheetWidth = 16; |
| 1921 | + int mapSheetHeight = 17; |
| 1922 | + |
| 1923 | + // TW suggests one map sheet per 4 units. We floor as we want to veer towards smaller maps, rather than |
| 1924 | + // larger. |
| 1925 | + double totalMapSheets = floor(unitCount / 4.0); |
| 1926 | + |
| 1927 | + // We want to keep scenario heights low to avoid players needing to spend several turns just traveling. |
| 1928 | + // We received feedback that while this allowed for more tactical maneuvers, it wasn't fun. |
| 1929 | + int mapSheetsTall = totalMapSheets >= 4 ? (int) floor(totalMapSheets / 2.0) : 1; |
| 1930 | + mapSheetsTall = max(1, mapSheetsTall + heightModifier + mapParameters.getAdditionalMapSheetTall()); |
| 1931 | + |
| 1932 | + // This creates a wide area of engagement which should help reduce the tendency for forces to 'death ball' |
| 1933 | + int mapSheetsWide = (int) floor(totalMapSheets / mapSheetsTall); |
| 1934 | + mapSheetsWide = max(minimumWidth, mapSheetsWide + mapParameters.getAdditionalMapSheetWide()); |
| 1935 | + |
| 1936 | + mapSizeX = mapSheetWidth * mapSheetsWide; |
| 1937 | + mapSizeY = mapSheetHeight * mapSheetsTall; |
1910 | 1938 | } else { |
1911 | | - mapSizeX = template.mapParameters.getBaseWidth(); |
1912 | | - mapSizeY = template.mapParameters.getBaseHeight(); |
1913 | | - } |
| 1939 | + mapSizeX = mapParameters.getBaseWidth(); |
| 1940 | + mapSizeY = mapParameters.getBaseHeight(); |
1914 | 1941 |
|
1915 | | - // increment map size by template-specified increments |
1916 | | - mapSizeX += template.mapParameters.getWidthScalingIncrement() * scenario.getForceCount(); |
1917 | | - mapSizeY += template.mapParameters.getHeightScalingIncrement() * scenario.getForceCount(); |
| 1942 | + // increment map size by template-specified increments |
| 1943 | + mapSizeX += mapParameters.getWidthScalingIncrement() * scenario.getForceCount(); |
| 1944 | + mapSizeY += mapParameters.getHeightScalingIncrement() * scenario.getForceCount(); |
| 1945 | + } |
1918 | 1946 |
|
1919 | 1947 | // 50/50 odds to rotate the map 90 degrees if specified. |
1920 | | - if (template.mapParameters.isAllowRotation()) { |
| 1948 | + if (mapParameters.isAllowRotation()) { |
1921 | 1949 | int roll = randomInt(20) + 1; |
1922 | 1950 | if (roll <= 10) { |
1923 | | - int swap = mapSizeX; |
1924 | | - mapSizeX = mapSizeY; |
1925 | | - mapSizeY = swap; |
| 1951 | + // Ignore the IDE telling you this is wrong |
| 1952 | + scenario.setMapSizeX(mapSizeY); |
| 1953 | + scenario.setMapSizeY(mapSizeX); |
1926 | 1954 | } |
1927 | 1955 | } |
1928 | 1956 |
|
@@ -2364,7 +2392,7 @@ private static List<Entity> fillTransport(AtBScenario scenario, Entity transport |
2364 | 2392 |
|
2365 | 2393 | double bayCapacity = bay.getUnused(); |
2366 | 2394 | int remainingCount = (int) max(1, |
2367 | | - Math.floor(bayCapacity / IUnitGenerator.FOOT_PLATOON_INFANTRY_WEIGHT)); |
| 2395 | + floor(bayCapacity / IUnitGenerator.FOOT_PLATOON_INFANTRY_WEIGHT)); |
2368 | 2396 | while (remainingCount > 0) { |
2369 | 2397 |
|
2370 | 2398 | // Set base random generation parameters |
|
0 commit comments