|
251 | 251 | import mekhq.campaign.universe.factionStanding.FactionAccoladeLevel; |
252 | 252 | import mekhq.campaign.universe.factionStanding.FactionCensureEvent; |
253 | 253 | import mekhq.campaign.universe.factionStanding.FactionCensureLevel; |
254 | | -import mekhq.campaign.universe.factionStanding.FactionStandingUltimatum; |
255 | 254 | import mekhq.campaign.universe.factionStanding.FactionStandingJudgmentType; |
| 255 | +import mekhq.campaign.universe.factionStanding.FactionStandingUltimatum; |
256 | 256 | import mekhq.campaign.universe.factionStanding.FactionStandingUtilities; |
257 | 257 | import mekhq.campaign.universe.factionStanding.FactionStandings; |
258 | 258 | import mekhq.campaign.universe.factionStanding.PerformBatchall; |
@@ -6607,6 +6607,21 @@ public boolean isPirateCampaign() { |
6607 | 6607 | return faction.getShortName().equals(PIRATE_FACTION_CODE); |
6608 | 6608 | } |
6609 | 6609 |
|
| 6610 | + /** |
| 6611 | + * Determines whether the current campaign is a mercenary campaign. |
| 6612 | + * |
| 6613 | + * <p>This method checks if the faction associated with the campaign is Mercenary, returning {@code true} if it is, |
| 6614 | + * and {@code false} otherwise.</p> |
| 6615 | + * |
| 6616 | + * @return {@code true} if the campaign is Mercenary, {@code false} otherwise. |
| 6617 | + * |
| 6618 | + * @author Illiani |
| 6619 | + * @since 0.50.07 |
| 6620 | + */ |
| 6621 | + public boolean isMercenaryCampaign() { |
| 6622 | + return faction.getShortName().equals(MERCENARY_FACTION_CODE); |
| 6623 | + } |
| 6624 | + |
6610 | 6625 | public void setFaction(final Faction faction) { |
6611 | 6626 | setFactionDirect(faction); |
6612 | 6627 | updateTechFactionCode(); |
@@ -10275,79 +10290,136 @@ public List<Entity> getAllCombatEntities() { |
10275 | 10290 | return units; |
10276 | 10291 | } |
10277 | 10292 |
|
10278 | | - |
10279 | 10293 | /** |
10280 | | - * Determines the appropriate starting planet for a new campaign. |
| 10294 | + * Determines the appropriate starting planet for a new campaign based on campaign type, faction, and various |
| 10295 | + * fallback scenarios. |
10281 | 10296 | * |
10282 | | - * <p>This method first attempts to obtain the starting planet from the campaign's primary method. If no valid |
10283 | | - * system is found, or if the result is "Terra" (which is the default value used when no system is set), it selects |
10284 | | - * a fallback faction's starting planet using the following logic:</p> |
| 10297 | + * <p>This method first checks if the campaign is classified as a mercenary or pirate campaign. If so, it |
| 10298 | + * delegates responsibility to {@link #getMercenaryOrPirateStartingPlanet(Factions, String)}, which implements |
| 10299 | + * special logic to handle those campaign types.</p> |
10285 | 10300 | * |
10286 | | - * <ul> |
10287 | | - * <li>If the faction is "PIR", a random pirate faction (other than "PIR" itself) with an available starting |
10288 | | - * planet is chosen, if available.</li> |
10289 | | - * <li>If the faction is a clan, the generic "CLAN" faction is used as the fallback.</li> |
10290 | | - * <li>If the faction is mercenary, 75% of the time the campaign will begin on the mercenary faction |
10291 | | - * capital. Otherwise, they will begin on the capital of another playable faction.</li> |
10292 | | - * <li>Otherwise, the default faction (Mercenary) is used as the fallback.</li> |
10293 | | - * </ul> |
| 10301 | + * <p>For all other campaign types, it uses the current campaign's faction to attempt to retrieve that faction’s |
| 10302 | + * canonical starting system for the current game date. If no valid system can be found (due to, for example, the |
| 10303 | + * faction not having a valid capital), the logic falls back to a default faction’s starting planet, and, if |
| 10304 | + * necessary, ultimately falls back to the planet Terra as a default universal location.</p> |
10294 | 10305 | * |
10295 | | - * <p>The returned result is always the system's primary planet.</p> |
| 10306 | + * <p>The method also includes special handling for Clan campaigns: if the fallback logic would result in the |
| 10307 | + * campaign starting on Terra but the campaign is clan-based, it attempts to relocate the starting planet to |
| 10308 | + * Strana Mechty.</p> |
10296 | 10309 | * |
10297 | | - * @return the {@link Planet} object representing the new campaign's starting planet |
| 10310 | + * @return the {@link Planet} instance where the campaign should start |
10298 | 10311 | * |
10299 | | - * @author Illiani |
10300 | 10312 | * @since 0.50.07 |
| 10313 | + * @author Illiani |
10301 | 10314 | */ |
10302 | 10315 | public Planet getNewCampaignStartingPlanet() { |
10303 | 10316 | Factions factions = Factions.getInstance(); |
10304 | 10317 |
|
10305 | | - PlanetarySystem startingSystem = faction.getStartingPlanet(this, currentDay); |
| 10318 | + final String TERRA_ID = "Terra"; |
| 10319 | + final String CLAN_CODE = "CLAN"; |
| 10320 | + |
| 10321 | + Faction startingFaction; |
| 10322 | + PlanetarySystem startingSystem; |
| 10323 | + |
| 10324 | + if (isMercenaryCampaign() || isPirateCampaign()) { |
| 10325 | + return getMercenaryOrPirateStartingPlanet(factions, TERRA_ID); |
| 10326 | + } |
| 10327 | + |
| 10328 | + // Default for non-merc/pirate campaigns |
| 10329 | + startingFaction = faction; |
| 10330 | + startingSystem = startingFaction.getStartingPlanet(this, currentDay); |
10306 | 10331 |
|
| 10332 | + // Fallback if the system is unavailable |
10307 | 10333 | if (startingSystem == null) { |
10308 | | - Faction fallbackFaction = factions.getDefaultFaction(); |
10309 | | - startingSystem = fallbackFaction.getStartingPlanet(this, currentDay); |
10310 | | - } else if (startingSystem.getId().equalsIgnoreCase("Terra")) { |
10311 | | - Faction fallbackFaction = factions.getDefaultFaction(); |
10312 | | - |
10313 | | - if (faction.getShortName().equalsIgnoreCase("PIR")) { |
10314 | | - List<Faction> pirateFactions = new ArrayList<>(); |
10315 | | - for (Faction activeFaction : factions.getActiveFactions(currentDay)) { |
10316 | | - if (activeFaction.isPirate() && |
10317 | | - !activeFaction.getShortName().equalsIgnoreCase("PIR")) { |
10318 | | - pirateFactions.add(activeFaction); |
10319 | | - } |
10320 | | - } |
| 10334 | + startingFaction = factions.getDefaultFaction(); |
| 10335 | + startingSystem = startingFaction.getStartingPlanet(this, currentDay); |
| 10336 | + if (startingSystem == null) { |
| 10337 | + startingSystem = Systems.getInstance().getSystemById(TERRA_ID); |
| 10338 | + } |
| 10339 | + } |
10321 | 10340 |
|
10322 | | - if (!pirateFactions.isEmpty()) { |
10323 | | - fallbackFaction = ObjectUtility.getRandomItem(pirateFactions); |
| 10341 | + // Special case: Clan campaign starting on Terra, swap to Clan homeworld |
| 10342 | + if (TERRA_ID.equals(startingSystem.getId()) && isClanCampaign()) { |
| 10343 | + Faction clanFaction = factions.getFaction(CLAN_CODE); |
| 10344 | + if (clanFaction != null) { |
| 10345 | + PlanetarySystem clanSystem = clanFaction.getStartingPlanet(this, currentDay); |
| 10346 | + if (clanSystem != null) { |
| 10347 | + startingSystem = clanSystem; |
10324 | 10348 | } |
10325 | | - } else if (faction.isClan()) { |
10326 | | - fallbackFaction = factions.getFaction("CLAN"); |
10327 | | - } else if (faction.getShortName().equalsIgnoreCase("MERC")) { |
10328 | | - // Most of the time, mercenary campaigns will begin on their faction capital (Galatea, etc.). |
10329 | | - // However, there is a 25% chance they begin in another faction's territory |
10330 | | - int roll = randomInt(4); |
| 10349 | + } |
| 10350 | + } |
10331 | 10351 |
|
10332 | | - if (roll == 0) { |
10333 | | - fallbackFaction = factions.getFaction("MERC"); |
10334 | | - } else { |
10335 | | - List<Faction> recruitingFaction = new ArrayList<>(); |
10336 | | - for (Faction activeFaction : factions.getActiveFactions(currentDay)) { |
10337 | | - if (activeFaction.isPlayable() && !activeFaction.isClan() && !activeFaction.isDeepPeriphery()) { |
10338 | | - recruitingFaction.add(activeFaction); |
10339 | | - } |
10340 | | - } |
| 10352 | + return startingSystem.getPrimaryPlanet(); |
| 10353 | + } |
| 10354 | + |
| 10355 | + /** |
| 10356 | + * Selects a starting planet for mercenary or pirate campaigns by considering eligible factions, campaign date, and |
| 10357 | + * appropriate weighting for periphery factions (if pirate). |
| 10358 | + * |
| 10359 | + * <p>For mercenary campaigns, the designated mercenary faction is used as the initial fallback. For pirate |
| 10360 | + * campaigns, the Tortuga Dominions are preferred, but only if they are active at the campaign's start date; |
| 10361 | + * otherwise, the game's configured default faction is used (usually Mercenary, but I opted not to hardcode |
| 10362 | + * mercenary here incase the default changes).</p> |
| 10363 | + * |
| 10364 | + * <p>There is a two-thirds probability that the starting faction will be selected from all factions, subject to |
| 10365 | + * several filters (playability, not a Clan, not deep periphery). For pirate campaigns, eligible periphery factions |
| 10366 | + * are intentionally added multiple times to the selection pool to increase their likelihood of being chosen |
| 10367 | + * (weighted randomness).</p> |
| 10368 | + * |
| 10369 | + * <p>After the faction is chosen, this method attempts to get that faction’s canonical starting world. If no |
| 10370 | + * valid system is found, the logic falls back to Terra, ensuring that the campaign always has a valid starting |
| 10371 | + * world even in case of missing data.</p> |
| 10372 | + * |
| 10373 | + * @param factions The {@link Factions} manager supplying access to all faction data. |
| 10374 | + * @param TERRA_ID The globally unique identifier for the planet Terra, used for the ultimate fallback. |
| 10375 | + * |
| 10376 | + * @return the {@link Planet} used as the campaign start location. |
| 10377 | + * |
| 10378 | + * @author Illiani |
| 10379 | + * @since 0.50.07 |
| 10380 | + */ |
| 10381 | + private Planet getMercenaryOrPirateStartingPlanet(Factions factions, String TERRA_ID) { |
| 10382 | + final String TORTUGA_CODE = "TD"; |
10341 | 10383 |
|
10342 | | - if (!recruitingFaction.isEmpty()) { |
10343 | | - fallbackFaction = ObjectUtility.getRandomItem(recruitingFaction); |
| 10384 | + PlanetarySystem startingSystem; |
| 10385 | + Faction startingFaction; |
| 10386 | + // Determine fallback faction for merc/pirate |
| 10387 | + startingFaction = isMercenaryCampaign() |
| 10388 | + ? factions.getFaction(MERCENARY_FACTION_CODE) |
| 10389 | + : factions.getFaction(TORTUGA_CODE); |
| 10390 | + |
| 10391 | + // If pirate fallback is unavailable at the campaign's start date, use the default faction |
| 10392 | + if (isPirateCampaign() && !startingFaction.validIn(currentDay)) { |
| 10393 | + startingFaction = factions.getDefaultFaction(); |
| 10394 | + } |
| 10395 | + |
| 10396 | + // 33% chance to start in fallback faction's capital |
| 10397 | + if (randomInt(3) != 0) { |
| 10398 | + // Pick a random, eligible recruiting faction |
| 10399 | + List<Faction> recruitingFactions = new ArrayList<>(); |
| 10400 | + for (Faction possibleFaction : factions.getActiveFactions(currentDay)) { |
| 10401 | + if (possibleFaction.isPlayable() && !possibleFaction.isClan() && !possibleFaction.isDeepPeriphery()) { |
| 10402 | + recruitingFactions.add(possibleFaction); |
| 10403 | + |
| 10404 | + // If we're playing a pirate campaign, we want to triple the chance that we start in the periphery |
| 10405 | + if (possibleFaction.isPeriphery() && isPirateCampaign()) { |
| 10406 | + recruitingFactions.add(possibleFaction); |
| 10407 | + recruitingFactions.add(possibleFaction); |
10344 | 10408 | } |
10345 | 10409 | } |
10346 | 10410 | } |
| 10411 | + if (!recruitingFactions.isEmpty()) { |
| 10412 | + startingFaction = ObjectUtility.getRandomItem(recruitingFactions); |
| 10413 | + } |
| 10414 | + } |
10347 | 10415 |
|
10348 | | - startingSystem = fallbackFaction.getStartingPlanet(this, currentDay); |
| 10416 | + startingSystem = startingFaction.getStartingPlanet(this, currentDay); |
| 10417 | + if (startingSystem != null) { |
| 10418 | + return startingSystem.getPrimaryPlanet(); |
10349 | 10419 | } |
10350 | 10420 |
|
10351 | | - return startingSystem.getPrimaryPlanet(); |
| 10421 | + // Fallback if no startingSystem |
| 10422 | + startingSystem = Systems.getInstance().getSystemById(TERRA_ID); |
| 10423 | + return startingSystem != null ? startingSystem.getPrimaryPlanet() : null; |
10352 | 10424 | } |
10353 | 10425 | } |
0 commit comments