From e596260430caf2e154a6dd8865af10a4a27dc26c Mon Sep 17 00:00:00 2001 From: Scoppio Date: Mon, 20 Jan 2025 10:13:26 -0300 Subject: [PATCH 01/12] feat: add some commands to better control Princess behavior, makes princess ignore ignored targets --- .../src/megamek/client/bot/ChatProcessor.java | 14 ++--- .../client/bot/princess/FireControl.java | 42 +++------------ .../NewtonianAerospacePathRanker.java | 23 ++++---- .../client/bot/princess/PathRanker.java | 52 +++++++++---------- .../client/bot/princess/RankedPath.java | 2 +- 5 files changed, 54 insertions(+), 79 deletions(-) diff --git a/megamek/src/megamek/client/bot/ChatProcessor.java b/megamek/src/megamek/client/bot/ChatProcessor.java index a0ed34532f7..15ad46b5e0f 100644 --- a/megamek/src/megamek/client/bot/ChatProcessor.java +++ b/megamek/src/megamek/client/bot/ChatProcessor.java @@ -19,14 +19,7 @@ */ package megamek.client.bot; -import java.util.StringTokenizer; -import java.util.stream.Collectors; - -import megamek.client.bot.princess.BehaviorSettings; -import megamek.client.bot.princess.BehaviorSettingsFactory; -import megamek.client.bot.princess.CardinalEdge; -import megamek.client.bot.princess.ChatCommands; -import megamek.client.bot.princess.Princess; +import megamek.client.bot.princess.*; import megamek.codeUtilities.StringUtility; import megamek.common.Coords; import megamek.common.Game; @@ -39,6 +32,9 @@ import megamek.server.commands.GameMasterCommand; import megamek.server.commands.JoinTeamCommand; +import java.util.StringTokenizer; +import java.util.stream.Collectors; + public class ChatProcessor { private final static MMLogger logger = MMLogger.create(ChatProcessor.class); @@ -451,7 +447,7 @@ void additionalPrincessCommands(GamePlayerChatEvent chatEvent, Princess princess // Specify a priority unit target. if (command.toLowerCase().startsWith(ChatCommands.SHOW_DISHONORED.getAbbreviation())) { msg = "Dishonored Player ids: " + princess.getHonorUtil().getDishonoredEnemies().stream() - .map(Object::toString).collect(Collectors.joining(", ")); + .map(Object::toString).collect(Collectors.joining(", ")); princess.sendChat(msg); logger.info(msg); } diff --git a/megamek/src/megamek/client/bot/princess/FireControl.java b/megamek/src/megamek/client/bot/princess/FireControl.java index ccef6431ea8..4f27a35e0ac 100644 --- a/megamek/src/megamek/client/bot/princess/FireControl.java +++ b/megamek/src/megamek/client/bot/princess/FireControl.java @@ -1374,7 +1374,7 @@ protected double calcPriorityUnitTargetUtility(final Targetable target) { return 0; } - final int id = ((Entity) target).getId(); + final int id = target.getId(); if (owner.getPriorityUnitTargets().contains(id)) { return PRIORITY_TARGET_UTILITY; } @@ -1546,31 +1546,6 @@ protected double calcTargetPotentialDamageMultiplier(final Targetable target) { // damage)). } - /** - * calculates the 'utility' of a physical action. - * - * @param physicalInfo The {@link PhysicalInfo} to be calculated. - */ - void calculateUtility(final PhysicalInfo physicalInfo) { - // If we can't hit, there's no point. - if (0.0 >= physicalInfo.getProbabilityToHit()) { - physicalInfo.setUtility(-10000); - return; - } - - double utility = DAMAGE_UTILITY * physicalInfo.getExpectedDamage(); - utility += CRITICAL_UTILITY * physicalInfo.getExpectedCriticals(); - utility += KILL_UTILITY * physicalInfo.getKillProbability(); - utility *= calcTargetPotentialDamageMultiplier(physicalInfo.getTarget()); - utility -= (physicalInfo.getTarget() instanceof MekWarrior) ? EJECTED_PILOT_DISUTILITY : 0; - utility += calcCommandUtility(physicalInfo.getTarget()); - utility += calcStrategicBuildingTargetUtility(physicalInfo.getTarget()); - utility += calcPriorityUnitTargetUtility(physicalInfo.getTarget()); - utility -= calcCivilianTargetDisutility(physicalInfo.getTarget()); - - physicalInfo.setUtility(utility); - } - /** * Creates a new {@link WeaponFireInfo} object containing data about firing * the given weapon at the given target. @@ -2705,19 +2680,17 @@ FiringPlan getBestFiringPlan(final Entity shooter, // Loop through each enemy and find the best plan for attacking them. for (final Targetable enemy : enemies) { - if (owner.getBehaviorSettings().getIgnoredUnitTargets().contains(enemy.getId())) { logger.info(enemy.getDisplayName() + " is being explicitly ignored"); continue; } + final int playerId = enemy.getOwnerId(); final boolean priorityTarget = owner.getPriorityUnitTargets().contains(enemy.getId()); - - // Skip retreating enemies so long as they haven't fired on me while retreating. - final int playerId = (enemy instanceof Entity) ? ((Entity) enemy).getOwnerId() : -1; - if (!priorityTarget && honorUtil.isEnemyBroken(enemy.getId(), playerId, - owner.getForcedWithdrawal())) { - logger.info(enemy.getDisplayName() + " is broken - ignoring"); + final boolean isEnemyBroken = honorUtil.isEnemyBroken(enemy.getId(), playerId, owner.getForcedWithdrawal()); + // Only skip retreating enemies that are not priority targets so long as they haven't fired on me while retreating. + if (!priorityTarget && isEnemyBroken) { + logger.info(enemy.getDisplayName() + " is broken and not priority - ignoring"); continue; } @@ -2727,7 +2700,8 @@ FiringPlan getBestFiringPlan(final Entity shooter, ammoConservation); final FiringPlan plan = determineBestFiringPlan(parameters); - if ((null == bestPlan) || (plan.getUtility() > bestPlan.getUtility())) { + if ((bestPlan == null) + || (plan.getUtility() > bestPlan.getUtility())) { bestPlan = plan; } } diff --git a/megamek/src/megamek/client/bot/princess/NewtonianAerospacePathRanker.java b/megamek/src/megamek/client/bot/princess/NewtonianAerospacePathRanker.java index 52d84ad6b89..f903157a683 100644 --- a/megamek/src/megamek/client/bot/princess/NewtonianAerospacePathRanker.java +++ b/megamek/src/megamek/client/bot/princess/NewtonianAerospacePathRanker.java @@ -39,24 +39,29 @@ public NewtonianAerospacePathRanker(Princess owningPrincess) { */ @Override public Entity findClosestEnemy(Entity me, Coords position, Game game) { - int range = 9999; + int range = Integer.MAX_VALUE; Entity closest = null; List enemies = getOwner().getEnemyEntities(); - for (Entity e : enemies) { - // Also, skip withdrawing enemy bot units, to avoid humping disabled tanks and ejected MekWarriors - if (getOwner().getHonorUtil().isEnemyBroken(e.getId(), e.getOwnerId(), getOwner().getForcedWithdrawal())) { + var ignoredTargets = getOwner().getBehaviorSettings().getIgnoredUnitTargets(); + var priorityTargets = getOwner().getBehaviorSettings().getPriorityUnitTargets(); + for (Entity enemy : enemies) { + // targets that are withdrawing and are not priorities are ignored + // targets in the ignore list are ignored + // therefore... a priority target in the ignore list is ignored + if ((!priorityTargets.contains(enemy.getId()) && getOwner().getHonorUtil().isEnemyBroken(enemy.getId(), enemy.getOwnerId(), getOwner().getForcedWithdrawal())) + || ignoredTargets.contains(enemy.getId())) { continue; } // If a unit has not moved, assume it will move away from me. int unmovedDistMod = 0; - if (e.isSelectableThisTurn() && !e.isImmobile()) { - unmovedDistMod = e.getWalkMP(); + if (enemy.isSelectableThisTurn() && !enemy.isImmobile()) { + unmovedDistMod = enemy.getWalkMP(); } - if ((position.distance(e.getPosition()) + unmovedDistMod) < range) { - range = position.distance(e.getPosition()); - closest = e; + if ((position.distance(enemy.getPosition()) + unmovedDistMod) < range) { + range = position.distance(enemy.getPosition()); + closest = enemy; } } return closest; diff --git a/megamek/src/megamek/client/bot/princess/PathRanker.java b/megamek/src/megamek/client/bot/princess/PathRanker.java index bc3c8062378..d895aa00996 100644 --- a/megamek/src/megamek/client/bot/princess/PathRanker.java +++ b/megamek/src/megamek/client/bot/princess/PathRanker.java @@ -19,6 +19,16 @@ */ package megamek.client.bot.princess; +import megamek.client.bot.princess.UnitBehavior.BehaviorType; +import megamek.client.ui.Messages; +import megamek.client.ui.SharedUtility; +import megamek.codeUtilities.StringUtility; +import megamek.common.*; +import megamek.common.annotations.Nullable; +import megamek.common.options.OptionsConstants; +import megamek.logging.MMLogger; +import org.apache.logging.log4j.Level; + import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; @@ -28,17 +38,6 @@ import java.util.Enumeration; import java.util.List; -import megamek.client.ui.Messages; -import org.apache.logging.log4j.Level; - -import megamek.client.bot.princess.UnitBehavior.BehaviorType; -import megamek.client.ui.SharedUtility; -import megamek.codeUtilities.StringUtility; -import megamek.common.*; -import megamek.common.annotations.Nullable; -import megamek.common.options.OptionsConstants; -import megamek.logging.MMLogger; - import static megamek.client.ui.SharedUtility.predictLeapDamage; import static megamek.client.ui.SharedUtility.predictLeapFallDamage; @@ -63,7 +62,7 @@ public enum PathRankerType { NewtonianAerospace } - private Princess owner; + private final Princess owner; public PathRanker(Princess princess) { owner = princess; @@ -275,31 +274,32 @@ public Targetable findClosestEnemy(Entity me, Coords position, Game game) { @Override public Targetable findClosestEnemy(Entity me, Coords position, Game game, boolean includeStrategicTargets) { - int range = 9999; + int range = Integer.MAX_VALUE; Targetable closest = null; List enemies = getOwner().getEnemyEntities(); - for (Entity e : enemies) { + var ignoredTargets = owner.getBehaviorSettings().getIgnoredUnitTargets(); + var priorityTargets = getOwner().getBehaviorSettings().getPriorityUnitTargets(); + for (Entity enemy : enemies) { // Skip airborne aero units as they're further away than they seem and hard to // catch. - // Also, skip withdrawing enemy bot units, to avoid humping disabled tanks and - // ejected - // MekWarriors - if (e.isAirborneAeroOnGroundMap() || - getOwner().getHonorUtil().isEnemyBroken(e.getId(), e.getOwnerId(), - getOwner().getForcedWithdrawal())) { + // Also, skip withdrawing enemy bot units that are not priority targets + // skip ignored units + if (enemy.isAirborneAeroOnGroundMap() + || (!priorityTargets.contains(enemy.getId()) && getOwner().getHonorUtil().isEnemyBroken(enemy.getId(), enemy.getOwnerId(), getOwner().getForcedWithdrawal())) + || ignoredTargets.contains(enemy.getId())) { continue; } // If a unit has not moved, assume it will move away from me. int unmovedDistMod = 0; - if (e.isSelectableThisTurn() && !e.isImmobile()) { - unmovedDistMod = e.getWalkMP(); + if (enemy.isSelectableThisTurn() && !enemy.isImmobile()) { + unmovedDistMod = enemy.getWalkMP(); } - int distance = position.distance(e.getPosition()); + int distance = position.distance(enemy.getPosition()); if ((distance + unmovedDistMod) < range) { range = distance; - closest = e; + closest = enemy; } } @@ -570,8 +570,8 @@ private boolean willBuildingCollapse(MovePath path, Game game) { return null; } - int xCenter = Math.round(xTotal / friendOnBoardCount); - int yCenter = Math.round(yTotal / friendOnBoardCount); + int xCenter = Math.round((float) xTotal / friendOnBoardCount); + int yCenter = Math.round((float) yTotal / friendOnBoardCount); Coords center = new Coords(xCenter, yCenter); if (!game.getBoard().contains(center)) { diff --git a/megamek/src/megamek/client/bot/princess/RankedPath.java b/megamek/src/megamek/client/bot/princess/RankedPath.java index a8595ade584..77d07782b99 100644 --- a/megamek/src/megamek/client/bot/princess/RankedPath.java +++ b/megamek/src/megamek/client/bot/princess/RankedPath.java @@ -27,7 +27,7 @@ * @author Deric "Netzilla" Page (deric dot page at usa dot net) * @since 12/5/13 10:19 AM */ -class RankedPath implements Comparable { +public class RankedPath implements Comparable { private MovePath path; private double rank; private String reason; From d614f8fed6a4872ae8432b12e197c10069791c8b Mon Sep 17 00:00:00 2001 From: Scoppio Date: Mon, 20 Jan 2025 11:10:43 -0300 Subject: [PATCH 02/12] fix: corrected value for calc ally center --- .../megamek/client/bot/princess/BasicPathRankerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/megamek/unittests/megamek/client/bot/princess/BasicPathRankerTest.java b/megamek/unittests/megamek/client/bot/princess/BasicPathRankerTest.java index c25880d0d0d..f6dbae54e5d 100644 --- a/megamek/unittests/megamek/client/bot/princess/BasicPathRankerTest.java +++ b/megamek/unittests/megamek/client/bot/princess/BasicPathRankerTest.java @@ -1028,7 +1028,7 @@ void testCalcAllyCenter() { friends.add(mockFriend4); // Test the default conditions. - Coords expected = new Coords(6, 6); + Coords expected = new Coords(7, 7); Coords actual = BasicPathRanker.calcAllyCenter(myId, friends, mockGame); assertCoordsEqual(expected, actual); From 38e023b21b7761578a98eb4e33f7c92507aadf59 Mon Sep 17 00:00:00 2001 From: Scoppio Date: Mon, 20 Jan 2025 11:58:05 -0300 Subject: [PATCH 03/12] fix: the bot should not consider hidden units in the list of available enemies --- megamek/src/megamek/client/bot/BotClient.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/megamek/src/megamek/client/bot/BotClient.java b/megamek/src/megamek/client/bot/BotClient.java index 2159f5f633d..7cf7a3e639d 100644 --- a/megamek/src/megamek/client/bot/BotClient.java +++ b/megamek/src/megamek/client/bot/BotClient.java @@ -363,9 +363,9 @@ public List getEnemyEntities() { currentTurnEnemyEntities = new ArrayList<>(); for (Entity entity : game.getEntitiesVector()) { if (entity.getOwner().isEnemyOf(getLocalPlayer()) - && (entity.getPosition() != null) && !entity.isOffBoard() - && (entity.getCrew() != null) && !entity.getCrew().isDead()) { - + && (entity.getPosition() != null) && !entity.isOffBoard() + && (entity.getCrew() != null) && !entity.getCrew().isDead() + && !entity.isHidden()) { currentTurnEnemyEntities.add(entity); } } From 9724539146521776548a3d7b1a4a753dd061e5c2 Mon Sep 17 00:00:00 2001 From: Richard J Hancock Date: Mon, 20 Jan 2025 09:13:04 -0600 Subject: [PATCH 04/12] Update history.txt --- megamek/docs/history.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/megamek/docs/history.txt b/megamek/docs/history.txt index 53b5d3405a6..6cafe1d9620 100644 --- a/megamek/docs/history.txt +++ b/megamek/docs/history.txt @@ -31,7 +31,7 @@ MEGAMEK VERSION HISTORY: + PR #6414: Warnings on Campaign Load - MegaMek Portion + Fix #6412: Fix TacOps "Standing Still" modifier description + Fix 6373: Fixed "unit that starts and ends a Movement Phase in liquid magma takes an additional damage" so it doesn't apply to units above the magma - ++ PR #6427 & #6428: Fix for Princess not ignoring Hidden and Ignored units. - Scoppio 0.50.02 (2024-12-30 2130 UTC) + PR #6183: New GM Commands, princess commands on map menu, graphics for some explosions From 6c5dc390d05825affb3873cbfc6076f61211bc0c Mon Sep 17 00:00:00 2001 From: psikomonkie <189469115+psikomonkie@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:18:32 -0500 Subject: [PATCH 05/12] Issue 6359: LAMs now properly consider if they're in fighter mode or not when deploying. --- megamek/src/megamek/client/ui/swing/DeploymentDisplay.java | 3 ++- megamek/src/megamek/server/totalwarfare/TWGameManager.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/megamek/src/megamek/client/ui/swing/DeploymentDisplay.java b/megamek/src/megamek/client/ui/swing/DeploymentDisplay.java index 2fa58acd54e..983127dce6f 100644 --- a/megamek/src/megamek/client/ui/swing/DeploymentDisplay.java +++ b/megamek/src/megamek/client/ui/swing/DeploymentDisplay.java @@ -534,8 +534,9 @@ public void hexMoused(BoardViewEvent b) { } } + // entity.isAero will check if a unit is a LAM in Fighter mode if ((entity instanceof IAero aero) - && (!(entity instanceof LandAirMek lam) || (lam.getConversionMode() == LandAirMek.CONV_MODE_FIGHTER))) { + && (entity.isAero())) { entity.setAltitude(finalElevation); if (finalElevation == 0) { aero.land(); diff --git a/megamek/src/megamek/server/totalwarfare/TWGameManager.java b/megamek/src/megamek/server/totalwarfare/TWGameManager.java index c8213e82ba1..1e3bb1daf1f 100644 --- a/megamek/src/megamek/server/totalwarfare/TWGameManager.java +++ b/megamek/src/megamek/server/totalwarfare/TWGameManager.java @@ -9287,7 +9287,8 @@ private void processDeployment(Entity entity, Coords coords, int nFacing, int el entity.setFacing(nFacing); entity.setSecondaryFacing(nFacing); - if (entity instanceof IAero aero) { + // entity.isAero will check if a unit is a LAM in Fighter mode + if (entity instanceof IAero aero && entity.isAero()) { entity.setAltitude(elevation); if ((elevation == 0) && !entity.isSpaceborne()) { aero.land(); From 54caf076a61d8caddac663d4aa29330ec5cb1532 Mon Sep 17 00:00:00 2001 From: psikomonkie <189469115+psikomonkie@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:02:24 -0500 Subject: [PATCH 06/12] Renamed Directory ProtomMek Pilots to ProtoMek Pilots in MegaMek to match MekHQ --- .../Proto_M_1.png | Bin .../Proto_M_10.png | Bin .../Proto_M_11.png | Bin .../Proto_M_12.png | Bin .../Proto_M_2.png | Bin .../Proto_M_3.png | Bin .../Proto_M_4.png | Bin .../Proto_M_5.png | Bin .../Proto_M_6.png | Bin .../Proto_M_7.png | Bin .../Proto_M_8.png | Bin .../Proto_M_9.png | Bin 12 files changed, 0 insertions(+), 0 deletions(-) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_1.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_10.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_11.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_12.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_2.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_3.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_4.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_5.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_6.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_7.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_8.png (100%) rename megamek/data/images/portraits/Male/{ProtomMek Pilot => ProtoMek Pilot}/Proto_M_9.png (100%) diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_1.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_1.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_1.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_1.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_10.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_10.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_10.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_10.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_11.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_11.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_11.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_11.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_12.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_12.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_12.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_12.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_2.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_2.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_2.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_2.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_3.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_3.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_3.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_3.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_4.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_4.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_4.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_4.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_5.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_5.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_5.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_5.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_6.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_6.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_6.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_6.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_7.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_7.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_7.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_7.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_8.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_8.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_8.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_8.png diff --git a/megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_9.png b/megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_9.png similarity index 100% rename from megamek/data/images/portraits/Male/ProtomMek Pilot/Proto_M_9.png rename to megamek/data/images/portraits/Male/ProtoMek Pilot/Proto_M_9.png From ccd6f370c081fe4f33b6121d2176bbededc00025 Mon Sep 17 00:00:00 2001 From: sleet01 Date: Tue, 21 Jan 2025 10:58:28 -0800 Subject: [PATCH 07/12] Initial fix: wrap all Artemis checks in "not-indirect" conditional --- .../megamek/common/weapons/LRMHandler.java | 177 +++++++++--------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/megamek/src/megamek/common/weapons/LRMHandler.java b/megamek/src/megamek/common/weapons/LRMHandler.java index 43b2ac615a7..49171a203a8 100644 --- a/megamek/src/megamek/common/weapons/LRMHandler.java +++ b/megamek/src/megamek/common/weapons/LRMHandler.java @@ -134,98 +134,96 @@ protected int calcHits(Vector vPhaseReport) { bECMAffected = true; } - if (((mLinker != null) && (mLinker.getType() instanceof MiscType) + if (!weapon.curMode().equals("Indirect")) { + if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS)) - && (atype.getMunitionType().contains(AmmoType.Munitions.M_ARTEMIS_CAPABLE)) - && !weapon.curMode().equals("Indirect")) { - if (bECMAffected) { - // ECM prevents bonus - Report r = new Report(3330); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else if (bMekTankStealthActive) { - // stealth prevents bonus - Report r = new Report(3335); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else { - nMissilesModifier += 2; - } - - } else if (((mLinker != null) + MiscType.F_ARTEMIS)) + && (atype.getMunitionType().contains(AmmoType.Munitions.M_ARTEMIS_CAPABLE))) { + if (bECMAffected) { + // ECM prevents bonus + Report r = new Report(3330); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else if (bMekTankStealthActive) { + // stealth prevents bonus + Report r = new Report(3335); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else { + nMissilesModifier += 2; + } + } else if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS_PROTO)) + MiscType.F_ARTEMIS_PROTO)) && (atype.getMunitionType().contains(AmmoType.Munitions.M_ARTEMIS_CAPABLE))) { - if (bECMAffected) { - // ECM prevents bonus - Report r = new Report(3330); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else if (bMekTankStealthActive) { - // stealth prevents bonus - Report r = new Report(3335); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else { - nMissilesModifier += 1; - } - - } else if (((mLinker != null) + if (bECMAffected) { + // ECM prevents bonus + Report r = new Report(3330); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else if (bMekTankStealthActive) { + // stealth prevents bonus + Report r = new Report(3335); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else { + nMissilesModifier += 1; + } + } else if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS_V)) + MiscType.F_ARTEMIS_V)) && (atype.getMunitionType().contains(AmmoType.Munitions.M_ARTEMIS_V_CAPABLE))) { - if (bECMAffected) { - // ECM prevents bonus - Report r = new Report(3330); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else if (bMekTankStealthActive) { - // stealth prevents bonus - Report r = new Report(3335); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else { - nMissilesModifier += 3; - } - } else if (atype.getAmmoType() == AmmoType.T_ATM) { - if (bECMAffected) { - // ECM prevents bonus - Report r = new Report(3330); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else if (bMekTankStealthActive) { - // stealth prevents bonus - Report r = new Report(3335); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else { - nMissilesModifier += 2; - } - } else if ((entityTarget != null) + if (bECMAffected) { + // ECM prevents bonus + Report r = new Report(3330); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else if (bMekTankStealthActive) { + // stealth prevents bonus + Report r = new Report(3335); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else { + nMissilesModifier += 3; + } + } else if (atype.getAmmoType() == AmmoType.T_ATM) { + if (bECMAffected) { + // ECM prevents bonus + Report r = new Report(3330); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else if (bMekTankStealthActive) { + // stealth prevents bonus + Report r = new Report(3335); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else { + nMissilesModifier += 2; + } + } else if ((entityTarget != null) && (entityTarget.isNarcedBy(ae.getOwner().getTeam()) || entityTarget - .isINarcedBy(ae.getOwner().getTeam()))) { - // only apply Narc bonus if we're not suffering ECM effect - // and we are using narc ammo, and we're not firing indirectly. - // narc capable missiles are only affected if the narc pod, which - // sits on the target, is ECM affected - boolean bTargetECMAffected = false; - bTargetECMAffected = ComputeECM.isAffectedByECM(ae, + .isINarcedBy(ae.getOwner().getTeam()))) { + // only apply Narc bonus if we're not suffering ECM effect + // and we are using narc ammo, and we're not firing indirectly. + // narc capable missiles are only affected if the narc pod, which + // sits on the target, is ECM affected + boolean bTargetECMAffected = false; + bTargetECMAffected = ComputeECM.isAffectedByECM(ae, target.getPosition(), target.getPosition()); - if (((atype.getAmmoType() == AmmoType.T_LRM) + if (((atype.getAmmoType() == AmmoType.T_LRM) || (atype.getAmmoType() == AmmoType.T_LRM_IMP) || (atype.getAmmoType() == AmmoType.T_SRM) || (atype.getAmmoType() == AmmoType.T_SRM_IMP) @@ -233,15 +231,16 @@ protected int calcHits(Vector vPhaseReport) { || (atype.getAmmoType() == AmmoType.T_NLRM)) && (atype.getMunitionType().contains(AmmoType.Munitions.M_NARC_CAPABLE)) && ((weapon.curMode() == null) || !weapon.curMode().equals( - "Indirect"))) { - if (bTargetECMAffected) { - // ECM prevents bonus - Report r = new Report(3330); - r.subject = subjectId; - r.newlines = 0; - vPhaseReport.addElement(r); - } else { - nMissilesModifier += 2; + "Indirect"))) { + if (bTargetECMAffected) { + // ECM prevents bonus + Report r = new Report(3330); + r.subject = subjectId; + r.newlines = 0; + vPhaseReport.addElement(r); + } else { + nMissilesModifier += 2; + } } } } From 80305ddcba7dbc63d6e0340c05e747a47592db63 Mon Sep 17 00:00:00 2001 From: sleet01 Date: Tue, 21 Jan 2025 11:15:39 -0800 Subject: [PATCH 08/12] Remove now-redundant check for NARC indirect --- megamek/src/megamek/common/weapons/LRMHandler.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/megamek/src/megamek/common/weapons/LRMHandler.java b/megamek/src/megamek/common/weapons/LRMHandler.java index 49171a203a8..866d77ad5e7 100644 --- a/megamek/src/megamek/common/weapons/LRMHandler.java +++ b/megamek/src/megamek/common/weapons/LRMHandler.java @@ -229,9 +229,7 @@ protected int calcHits(Vector vPhaseReport) { || (atype.getAmmoType() == AmmoType.T_SRM_IMP) || (atype.getAmmoType() == AmmoType.T_MML) || (atype.getAmmoType() == AmmoType.T_NLRM)) - && (atype.getMunitionType().contains(AmmoType.Munitions.M_NARC_CAPABLE)) - && ((weapon.curMode() == null) || !weapon.curMode().equals( - "Indirect"))) { + && (atype.getMunitionType().contains(AmmoType.Munitions.M_NARC_CAPABLE))) { if (bTargetECMAffected) { // ECM prevents bonus Report r = new Report(3330); From 50f43e9be8b6e1699048a361cef4469bc9b2e4d4 Mon Sep 17 00:00:00 2001 From: sleet01 Date: Tue, 21 Jan 2025 11:55:53 -0800 Subject: [PATCH 09/12] Fix Artemis V to-hit bonus applying to indirect --- megamek/src/megamek/common/actions/WeaponAttackAction.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/megamek/src/megamek/common/actions/WeaponAttackAction.java b/megamek/src/megamek/common/actions/WeaponAttackAction.java index f3877de4896..5780b412018 100644 --- a/megamek/src/megamek/common/actions/WeaponAttackAction.java +++ b/megamek/src/megamek/common/actions/WeaponAttackAction.java @@ -3352,6 +3352,7 @@ private static ToHitData compileAmmoToHitMods(Game game, Entity ae, Targetable t } // Missile Munitions + boolean isIndirect = weapon.hasModes() && (weapon.curMode().isIndirect()); // Apollo FCS for MRMs if (bApollo) { @@ -3359,7 +3360,7 @@ private static ToHitData compileAmmoToHitMods(Game game, Entity ae, Targetable t } // add Artemis V bonus - if (bArtemisV) { + if (bArtemisV && !isIndirect) { toHit.addModifier(-1, Messages.getString("WeaponAttackAction.ArtemisV")); } From ef82574fbb82a03ad0144d46572612740585cd6c Mon Sep 17 00:00:00 2001 From: Sleet01 Date: Tue, 21 Jan 2025 14:07:23 -0800 Subject: [PATCH 10/12] Update history.txt --- megamek/docs/history.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/megamek/docs/history.txt b/megamek/docs/history.txt index 6cafe1d9620..8d05b85a261 100644 --- a/megamek/docs/history.txt +++ b/megamek/docs/history.txt @@ -32,6 +32,7 @@ MEGAMEK VERSION HISTORY: + Fix #6412: Fix TacOps "Standing Still" modifier description + Fix 6373: Fixed "unit that starts and ends a Movement Phase in liquid magma takes an additional damage" so it doesn't apply to units above the magma + PR #6427 & #6428: Fix for Princess not ignoring Hidden and Ignored units. - Scoppio ++ PR #6431: Fix Artemis derivatives getting bonus on indirect fire 0.50.02 (2024-12-30 2130 UTC) + PR #6183: New GM Commands, princess commands on map menu, graphics for some explosions From 0ddfc40dc915453054d77a93bb49097b69b88de4 Mon Sep 17 00:00:00 2001 From: Sleet01 Date: Tue, 21 Jan 2025 14:28:12 -0800 Subject: [PATCH 11/12] Update history.txt --- megamek/docs/history.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/megamek/docs/history.txt b/megamek/docs/history.txt index 8d05b85a261..1abefb470da 100644 --- a/megamek/docs/history.txt +++ b/megamek/docs/history.txt @@ -33,6 +33,7 @@ MEGAMEK VERSION HISTORY: + Fix 6373: Fixed "unit that starts and ends a Movement Phase in liquid magma takes an additional damage" so it doesn't apply to units above the magma + PR #6427 & #6428: Fix for Princess not ignoring Hidden and Ignored units. - Scoppio + PR #6431: Fix Artemis derivatives getting bonus on indirect fire ++ PR #6430: Renamed Directory ProtomMek Pilots to ProtoMek Pilots in MegaMek to match MekHQ 0.50.02 (2024-12-30 2130 UTC) + PR #6183: New GM Commands, princess commands on map menu, graphics for some explosions From a6522b43a6bb8d688e567539493ccbf474d22d61 Mon Sep 17 00:00:00 2001 From: Sleet01 Date: Tue, 21 Jan 2025 14:29:45 -0800 Subject: [PATCH 12/12] Update history.txt --- megamek/docs/history.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/megamek/docs/history.txt b/megamek/docs/history.txt index 1abefb470da..bac9084fe61 100644 --- a/megamek/docs/history.txt +++ b/megamek/docs/history.txt @@ -34,6 +34,7 @@ MEGAMEK VERSION HISTORY: + PR #6427 & #6428: Fix for Princess not ignoring Hidden and Ignored units. - Scoppio + PR #6431: Fix Artemis derivatives getting bonus on indirect fire + PR #6430: Renamed Directory ProtomMek Pilots to ProtoMek Pilots in MegaMek to match MekHQ ++ Fix #6359: LAMs now properly consider if they're in fighter mode or not when deploying. 0.50.02 (2024-12-30 2130 UTC) + PR #6183: New GM Commands, princess commands on map menu, graphics for some explosions