From fec6beffc634228e6386687e6b07856595b8e0d4 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 9 Jun 2023 10:30:32 +0200 Subject: [PATCH 1/4] Pilot SPAs: Only allow non-bay wps for Wp Specialist; bonus for bays when all wps match --- .../client/ui/swing/CustomMechDialog.java | 20 +--- .../src/megamek/common/PilotSPAHelper.java | 95 +++++++++++++++++++ .../common/actions/WeaponAttackAction.java | 30 +++--- .../src/megamek/common/options/Option.java | 2 +- 4 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 megamek/src/megamek/common/PilotSPAHelper.java diff --git a/megamek/src/megamek/client/ui/swing/CustomMechDialog.java b/megamek/src/megamek/client/ui/swing/CustomMechDialog.java index d8d7bd99980..91ecd6cdca4 100644 --- a/megamek/src/megamek/client/ui/swing/CustomMechDialog.java +++ b/megamek/src/megamek/client/ui/swing/CustomMechDialog.java @@ -24,6 +24,7 @@ import megamek.common.util.fileUtils.MegaMekFile; import megamek.common.verifier.*; import megamek.common.weapons.bayweapons.ArtilleryBayWeapon; +import megamek.common.weapons.bayweapons.BayWeapon; import megamek.common.weapons.bayweapons.CapitalMissileBayWeapon; import javax.swing.*; @@ -34,6 +35,7 @@ import java.awt.event.*; import java.util.List; import java.util.*; +import java.util.stream.Collectors; /** * A dialog that a player can use to customize his mech before battle. @@ -326,27 +328,13 @@ private void addOption(IOption option, GridBagLayout gridbag, GridBagConstraints if ((OptionsConstants.GUNNERY_WEAPON_SPECIALIST).equals(option.getName())) { optionComp.addValue(Messages.getString("CustomMechDialog.None")); - TreeSet uniqueWeapons = new TreeSet<>(); - for (int i = 0; i < entity.getWeaponList().size(); i++) { - Mounted m = entity.getWeaponList().get(i); - uniqueWeapons.add(m.getName()); - } - for (String name : uniqueWeapons) { - optionComp.addValue(name); - } + PilotSPAHelper.weaponSpecialistValidWeaponNames(entity).forEach(optionComp::addValue); optionComp.setSelected(option.stringValue()); } if ((OptionsConstants.GUNNERY_SANDBLASTER).equals(option.getName())) { optionComp.addValue(Messages.getString("CustomMechDialog.None")); - TreeSet uniqueWeapons = new TreeSet<>(); - for (int i = 0; i < entity.getWeaponList().size(); i++) { - Mounted m = entity.getWeaponList().get(i); - uniqueWeapons.add(m.getName()); - } - for (String name : uniqueWeapons) { - optionComp.addValue(name); - } + PilotSPAHelper.sandblasterValidWeaponNames(entity).forEach(optionComp::addValue); optionComp.setSelected(option.stringValue()); } diff --git a/megamek/src/megamek/common/PilotSPAHelper.java b/megamek/src/megamek/common/PilotSPAHelper.java new file mode 100644 index 00000000000..7a939b21f7b --- /dev/null +++ b/megamek/src/megamek/common/PilotSPAHelper.java @@ -0,0 +1,95 @@ +package megamek.common; + +import megamek.common.weapons.autocannons.LBXACWeapon; +import megamek.common.weapons.autocannons.UACWeapon; +import megamek.common.weapons.bayweapons.BayWeapon; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * This class contains helper methods for Special Pilot Abilities. + */ +public final class PilotSPAHelper { + + /** @return True when the given Mounted equipment is a valid choice for the Weapons Specialist SPA. */ + public static boolean isWeaponSpecialistValid(Mounted mounted) { + return isWeaponSpecialistValid(mounted.getType()); + } + + /** @return True when the given EquipmentType is a valid choice for the Weapons Specialist SPA. */ + public static boolean isWeaponSpecialistValid(EquipmentType equipmentType) { + return (equipmentType instanceof WeaponType) && !(equipmentType instanceof BayWeapon) + && !equipmentType.hasFlag(WeaponType.F_AMS) && !equipmentType.is("Screen Launcher"); + } + + /** + * Returns a List of distinct (each occuring only once) weapon names of weapons present on the given + * Entity that are valid choices for the Weapon Specialist SPA. + * + * @return A list of weapon names from the given Entity that are valid choices for the Weapon Specialist SPA + */ + public static List weaponSpecialistValidWeaponNames(Entity entity) { + return entity.getTotalWeaponList().stream() + .map(Mounted::getType) + .filter(PilotSPAHelper::isWeaponSpecialistValid) + .map(EquipmentType::getName) + .distinct() + .collect(Collectors.toList()); + } + + /** + * Returns a List of weapons from those present on the given Entity that are valid choices for the + * Weapon Specialist SPA. Unlike {@link #weaponSpecialistValidWeaponNames(Entity)}, weapons + * appear in this list as often as they are present on the given Entity. + * + * @return A list of weapons from the given Entity that are valid choices for the Weapon Specialist SPA + */ + public static List weaponSpecialistValidWeapons(Entity entity) { + return entity.getTotalWeaponList().stream() + .filter(PilotSPAHelper::isWeaponSpecialistValid) + .collect(Collectors.toList()); + } + + /** @return True when the given Mounted equipment is a valid choice for the Sandblaster SPA. */ + public static boolean isSandblasterValid(Mounted mounted) { + return isSandblasterValid(mounted.getType()); + } + + /** @return True when the given EquipmentType is a valid choice for the Sandblaster SPA. */ + public static boolean isSandblasterValid(EquipmentType equipmentType) { + return (equipmentType instanceof WeaponType) + && ((equipmentType instanceof UACWeapon) || (equipmentType instanceof LBXACWeapon) + || ((WeaponType) equipmentType).damage == WeaponType.DAMAGE_BY_CLUSTERTABLE); + } + + /** + * Returns a List of distinct (each occuring only once) weapon names of weapons present on the given + * Entity that are valid choices for the Sandblaster SPA. + * + * @return A list of weapon names from the given Entity that are valid choices for the Sandblaster SPA + */ + public static List sandblasterValidWeaponNames(Entity entity) { + return entity.getTotalWeaponList().stream() + .map(Mounted::getType) + .filter(PilotSPAHelper::isSandblasterValid) + .map(EquipmentType::getName) + .distinct() + .collect(Collectors.toList()); + } + + /** + * Returns a List of weapons from those present on the given Entity that are valid choices for the + * Sandblaster SPA. Unlike {@link #sandblasterValidWeaponNames(Entity)}, weapons + * appear in this list as often as they are present on the given Entity. + * + * @return A list of weapons from the given Entity that are valid choices for the Sandblaster SPA + */ + public static List sandblasterValidWeapons(Entity entity) { + return entity.getTotalWeaponList().stream() + .filter(PilotSPAHelper::isSandblasterValid) + .collect(Collectors.toList()); + } + + private PilotSPAHelper() { } +} diff --git a/megamek/src/megamek/common/actions/WeaponAttackAction.java b/megamek/src/megamek/common/actions/WeaponAttackAction.java index 7b393e0c987..2c3e92d3175 100644 --- a/megamek/src/megamek/common/actions/WeaponAttackAction.java +++ b/megamek/src/megamek/common/actions/WeaponAttackAction.java @@ -23,10 +23,7 @@ import megamek.common.weapons.Weapon; import megamek.common.weapons.artillery.ArtilleryCannonWeapon; import megamek.common.weapons.artillery.ArtilleryWeapon; -import megamek.common.weapons.bayweapons.LaserBayWeapon; -import megamek.common.weapons.bayweapons.PPCBayWeapon; -import megamek.common.weapons.bayweapons.PulseLaserBayWeapon; -import megamek.common.weapons.bayweapons.ScreenLauncherBayWeapon; +import megamek.common.weapons.bayweapons.*; import megamek.common.weapons.capitalweapons.CapitalMissileWeapon; import megamek.common.weapons.gaussrifles.GaussWeapon; import megamek.common.weapons.gaussrifles.ISHGaussRifle; @@ -696,7 +693,7 @@ private static ToHitData toHit(Game game, int attackerId, Targetable target, int toHit = compileEnvironmentalToHitMods(game, ae, target, wtype, atype, toHit, isArtilleryIndirect); // Collect the modifiers for the crew/pilot - toHit = compileCrewToHitMods(game, ae, te, toHit, wtype); + toHit = compileCrewToHitMods(game, ae, te, toHit, weapon); // Collect the modifiers for the attacker's condition/actions if (ae != null) { @@ -3922,11 +3919,10 @@ else if (wtype.getAtClass() == WeaponType.CLASS_LBX_AC) { * @param ae The Entity making this attack * @param te The target Entity * @param toHit The running total ToHitData for this WeaponAttackAction - * - * @param wtype The WeaponType of the weapon being used + * @param weapon The weapon being used (it's type should be WeaponType!) * */ - private static ToHitData compileCrewToHitMods(Game game, Entity ae, Entity te, ToHitData toHit, WeaponType wtype) { + private static ToHitData compileCrewToHitMods(Game game, Entity ae, Entity te, ToHitData toHit, Mounted weapon) { if (ae == null) { // These checks won't work without a valid attacker @@ -3991,6 +3987,8 @@ private static ToHitData compileCrewToHitMods(Game game, Entity ae, Entity te, T toHit.addModifier(-1, Messages.getString("WeaponAttackAction.Vdni")); } + WeaponType wtype = ((weapon != null) && (weapon.getType() instanceof WeaponType)) ? (WeaponType) weapon.getType() : null; + if (ae.isConventionalInfantry()) { // check for cyber eye laser sighting on ranged attacks if (ae.hasAbility(OptionsConstants.MD_CYBER_IMP_LASER) @@ -4018,15 +4016,17 @@ private static ToHitData compileCrewToHitMods(Game game, Entity ae, Entity te, T } // Is the pilot a weapon specialist? - if (wtype != null && ae.hasAbility(OptionsConstants.GUNNERY_WEAPON_SPECIALIST, wtype.getName())) { + if (wtype instanceof BayWeapon + && weapon.getBayWeapons().stream().map(ae::getEquipment) + .allMatch(w -> ae.hasAbility(OptionsConstants.GUNNERY_WEAPON_SPECIALIST, w.getName()))) { + // All weapons in a bay must match the specialization + toHit.addModifier(-2, Messages.getString("WeaponAttackAction.WeaponSpec")); + } else if (wtype != null && ae.hasAbility(OptionsConstants.GUNNERY_WEAPON_SPECIALIST, wtype.getName())) { toHit.addModifier(-2, Messages.getString("WeaponAttackAction.WeaponSpec")); } else if (ae.hasAbility(OptionsConstants.GUNNERY_SPECIALIST)) { - // aToW style gunnery specialist: -1 to specialized weapon and +1 to - // all other weapons - // Note that weapon specialist supersedes gunnery specialization, so - // if you have - // a specialization in Medium Lasers and a Laser specialization, you - // only get the -2 specialization mod + // aToW style gunnery specialist: -1 to specialized weapon and +1 to all other weapons + // Note that weapon specialist supersedes gunnery specialization, so if you have + // a specialization in Medium Lasers and a Laser specialization, you only get the -2 specialization mod if (wtype != null && wtype.hasFlag(WeaponType.F_ENERGY)) { if (ae.hasAbility(OptionsConstants.GUNNERY_SPECIALIST, Crew.SPECIAL_ENERGY)) { toHit.addModifier(-1, Messages.getString("WeaponAttackAction.EnergySpec")); diff --git a/megamek/src/megamek/common/options/Option.java b/megamek/src/megamek/common/options/Option.java index 2f0f9a9c468..de99ea44594 100755 --- a/megamek/src/megamek/common/options/Option.java +++ b/megamek/src/megamek/common/options/Option.java @@ -87,7 +87,7 @@ public String getName() { public String getDisplayableNameWithValue() { updateInfo(); return info.getDisplayableName() - + (type == IOption.INTEGER ? " " + value : ""); + + ((type == IOption.INTEGER) || (type == IOption.CHOICE) ? " [" + value + "]" : ""); } @Override From 1126fa6bbc3ab4188a2ce6c2a4b8b2752c669244 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 10 Jun 2023 16:52:56 +0200 Subject: [PATCH 2/4] Pilot SPAs: Improve weapon filters, consider Rapid Fire AC option --- .../client/ui/swing/CustomMechDialog.java | 2 +- .../src/megamek/common/PilotSPAHelper.java | 74 +++++++++++++++---- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/megamek/src/megamek/client/ui/swing/CustomMechDialog.java b/megamek/src/megamek/client/ui/swing/CustomMechDialog.java index 91ecd6cdca4..ecac6ec405e 100644 --- a/megamek/src/megamek/client/ui/swing/CustomMechDialog.java +++ b/megamek/src/megamek/client/ui/swing/CustomMechDialog.java @@ -334,7 +334,7 @@ private void addOption(IOption option, GridBagLayout gridbag, GridBagConstraints if ((OptionsConstants.GUNNERY_SANDBLASTER).equals(option.getName())) { optionComp.addValue(Messages.getString("CustomMechDialog.None")); - PilotSPAHelper.sandblasterValidWeaponNames(entity).forEach(optionComp::addValue); + PilotSPAHelper.sandblasterValidWeaponNames(entity, gameOptions()).forEach(optionComp::addValue); optionComp.setSelected(option.stringValue()); } diff --git a/megamek/src/megamek/common/PilotSPAHelper.java b/megamek/src/megamek/common/PilotSPAHelper.java index 7a939b21f7b..b1cc5a3d229 100644 --- a/megamek/src/megamek/common/PilotSPAHelper.java +++ b/megamek/src/megamek/common/PilotSPAHelper.java @@ -1,8 +1,32 @@ +/* + * Copyright (c) 2023 - The MegaMek Team. All Rights Reserved. + * + * This file is part of MegaMek. + * + * MegaMek is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MegaMek is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MegaMek. If not, see . + */ package megamek.common; +import megamek.common.annotations.Nullable; +import megamek.common.options.GameOptions; +import megamek.common.options.OptionsConstants; +import megamek.common.weapons.autocannons.ACWeapon; import megamek.common.weapons.autocannons.LBXACWeapon; import megamek.common.weapons.autocannons.UACWeapon; import megamek.common.weapons.bayweapons.BayWeapon; +import megamek.common.weapons.lrms.StreakLRMWeapon; +import megamek.common.weapons.srms.StreakSRMWeapon; import java.util.List; import java.util.stream.Collectors; @@ -20,7 +44,8 @@ public static boolean isWeaponSpecialistValid(Mounted mounted) { /** @return True when the given EquipmentType is a valid choice for the Weapons Specialist SPA. */ public static boolean isWeaponSpecialistValid(EquipmentType equipmentType) { return (equipmentType instanceof WeaponType) && !(equipmentType instanceof BayWeapon) - && !equipmentType.hasFlag(WeaponType.F_AMS) && !equipmentType.is("Screen Launcher"); + && !equipmentType.hasFlag(WeaponType.F_AMS) && !equipmentType.is("Screen Launcher") + && !equipmentType.hasFlag(WeaponType.F_C3M) && !equipmentType.hasFlag(WeaponType.F_C3MBS); } /** @@ -51,16 +76,34 @@ public static List weaponSpecialistValidWeapons(Entity entity) { .collect(Collectors.toList()); } - /** @return True when the given Mounted equipment is a valid choice for the Sandblaster SPA. */ - public static boolean isSandblasterValid(Mounted mounted) { - return isSandblasterValid(mounted.getType()); + /** + * Returns true when the given Mounted equipment is a valid choice for the Sandblaster SPA, taking into account + * the given GameOptions, particularly, if TacOps RapidFire Autocannons is in use. When the given GameOptions + * is null, TacOps RapidFire Autocannons is assumed off. When TacOps RapidFire Autocannons is off, + * standard ACs are considered invalid. + * + * @return True when the given EquipmentType is a valid choice for the Sandblaster SPA. + */ + public static boolean isSandblasterValid(Mounted mounted, @Nullable GameOptions options) { + return isSandblasterValid(mounted.getType(), options); } - /** @return True when the given EquipmentType is a valid choice for the Sandblaster SPA. */ - public static boolean isSandblasterValid(EquipmentType equipmentType) { + /** + * Returns true when the given EquipmentType is a valid choice for the Sandblaster SPA, taking into account + * the given GameOptions, particularly, if TacOps RapidFire Autocannons is in use. When the given GameOptions + * is null, TacOps RapidFire Autocannons is assumed off. When TacOps RapidFire Autocannons is off, + * standard ACs are considered invalid. + * + * @return True when the given EquipmentType is a valid choice for the Sandblaster SPA. + */ + public static boolean isSandblasterValid(EquipmentType equipmentType, @Nullable GameOptions options) { + boolean rapidFireAC = (options != null) && options.booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_RAPID_AC) + && (equipmentType instanceof ACWeapon); + return (equipmentType instanceof WeaponType) - && ((equipmentType instanceof UACWeapon) || (equipmentType instanceof LBXACWeapon) - || ((WeaponType) equipmentType).damage == WeaponType.DAMAGE_BY_CLUSTERTABLE); + && ((equipmentType instanceof UACWeapon) || (equipmentType instanceof LBXACWeapon) || rapidFireAC + || ((WeaponType) equipmentType).damage == WeaponType.DAMAGE_BY_CLUSTERTABLE) + && !(equipmentType instanceof StreakLRMWeapon) && !(equipmentType instanceof StreakSRMWeapon); } /** @@ -69,27 +112,26 @@ public static boolean isSandblasterValid(EquipmentType equipmentType) { * * @return A list of weapon names from the given Entity that are valid choices for the Sandblaster SPA */ - public static List sandblasterValidWeaponNames(Entity entity) { + public static List sandblasterValidWeaponNames(Entity entity, @Nullable GameOptions options) { return entity.getTotalWeaponList().stream() - .map(Mounted::getType) - .filter(PilotSPAHelper::isSandblasterValid) - .map(EquipmentType::getName) + .filter(mounted -> isSandblasterValid(mounted, options)) + .map(Mounted::getName) .distinct() .collect(Collectors.toList()); } /** * Returns a List of weapons from those present on the given Entity that are valid choices for the - * Sandblaster SPA. Unlike {@link #sandblasterValidWeaponNames(Entity)}, weapons + * Sandblaster SPA. Unlike {@link #sandblasterValidWeaponNames(Entity, GameOptions)}, weapons * appear in this list as often as they are present on the given Entity. * * @return A list of weapons from the given Entity that are valid choices for the Sandblaster SPA */ - public static List sandblasterValidWeapons(Entity entity) { + public static List sandblasterValidWeapons(Entity entity, @Nullable GameOptions options) { return entity.getTotalWeaponList().stream() - .filter(PilotSPAHelper::isSandblasterValid) + .filter(mounted -> isSandblasterValid(mounted, options)) .collect(Collectors.toList()); } private PilotSPAHelper() { } -} +} \ No newline at end of file From 0f1638c30fd36d6d87edb8b5faa0a7c135d62f15 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 20 Jun 2023 19:20:25 +0200 Subject: [PATCH 3/4] Pilot SPAs: Allow Streaks for Sandblaster (AECM makes them roll cluster), disallow Inf. attacks for weapon spec. --- megamek/src/megamek/common/PilotSPAHelper.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/megamek/src/megamek/common/PilotSPAHelper.java b/megamek/src/megamek/common/PilotSPAHelper.java index b1cc5a3d229..e77212a15ae 100644 --- a/megamek/src/megamek/common/PilotSPAHelper.java +++ b/megamek/src/megamek/common/PilotSPAHelper.java @@ -25,8 +25,6 @@ import megamek.common.weapons.autocannons.LBXACWeapon; import megamek.common.weapons.autocannons.UACWeapon; import megamek.common.weapons.bayweapons.BayWeapon; -import megamek.common.weapons.lrms.StreakLRMWeapon; -import megamek.common.weapons.srms.StreakSRMWeapon; import java.util.List; import java.util.stream.Collectors; @@ -45,7 +43,8 @@ public static boolean isWeaponSpecialistValid(Mounted mounted) { public static boolean isWeaponSpecialistValid(EquipmentType equipmentType) { return (equipmentType instanceof WeaponType) && !(equipmentType instanceof BayWeapon) && !equipmentType.hasFlag(WeaponType.F_AMS) && !equipmentType.is("Screen Launcher") - && !equipmentType.hasFlag(WeaponType.F_C3M) && !equipmentType.hasFlag(WeaponType.F_C3MBS); + && !equipmentType.hasFlag(WeaponType.F_C3M) && !equipmentType.hasFlag(WeaponType.F_C3MBS) + && !equipmentType.hasFlag(WeaponType.F_INFANTRY_ATTACK); } /** @@ -102,8 +101,7 @@ public static boolean isSandblasterValid(EquipmentType equipmentType, @Nullable return (equipmentType instanceof WeaponType) && ((equipmentType instanceof UACWeapon) || (equipmentType instanceof LBXACWeapon) || rapidFireAC - || ((WeaponType) equipmentType).damage == WeaponType.DAMAGE_BY_CLUSTERTABLE) - && !(equipmentType instanceof StreakLRMWeapon) && !(equipmentType instanceof StreakSRMWeapon); + || ((WeaponType) equipmentType).damage == WeaponType.DAMAGE_BY_CLUSTERTABLE); } /** From 05c131a38160be3925482a4fba1fde061eac3a1e Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 21 Jun 2023 17:05:57 +0200 Subject: [PATCH 4/4] Pilot SPAs: Allow AMS with AMS as weapon game option for weapon specialist --- .../client/ui/swing/CustomMechDialog.java | 2 +- .../src/megamek/common/PilotSPAHelper.java | 22 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/megamek/src/megamek/client/ui/swing/CustomMechDialog.java b/megamek/src/megamek/client/ui/swing/CustomMechDialog.java index ecac6ec405e..a2c196429e2 100644 --- a/megamek/src/megamek/client/ui/swing/CustomMechDialog.java +++ b/megamek/src/megamek/client/ui/swing/CustomMechDialog.java @@ -328,7 +328,7 @@ private void addOption(IOption option, GridBagLayout gridbag, GridBagConstraints if ((OptionsConstants.GUNNERY_WEAPON_SPECIALIST).equals(option.getName())) { optionComp.addValue(Messages.getString("CustomMechDialog.None")); - PilotSPAHelper.weaponSpecialistValidWeaponNames(entity).forEach(optionComp::addValue); + PilotSPAHelper.weaponSpecialistValidWeaponNames(entity, gameOptions()).forEach(optionComp::addValue); optionComp.setSelected(option.stringValue()); } diff --git a/megamek/src/megamek/common/PilotSPAHelper.java b/megamek/src/megamek/common/PilotSPAHelper.java index e77212a15ae..b6bffdef6af 100644 --- a/megamek/src/megamek/common/PilotSPAHelper.java +++ b/megamek/src/megamek/common/PilotSPAHelper.java @@ -35,14 +35,18 @@ public final class PilotSPAHelper { /** @return True when the given Mounted equipment is a valid choice for the Weapons Specialist SPA. */ - public static boolean isWeaponSpecialistValid(Mounted mounted) { - return isWeaponSpecialistValid(mounted.getType()); + public static boolean isWeaponSpecialistValid(Mounted mounted, @Nullable GameOptions options) { + return isWeaponSpecialistValid(mounted.getType(), options); } /** @return True when the given EquipmentType is a valid choice for the Weapons Specialist SPA. */ - public static boolean isWeaponSpecialistValid(EquipmentType equipmentType) { + public static boolean isWeaponSpecialistValid(EquipmentType equipmentType, @Nullable GameOptions options) { + boolean amsAsWeapon = (options != null) && options.booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_MANUAL_AMS) + && (equipmentType.hasFlag(WeaponType.F_AMS)); + return (equipmentType instanceof WeaponType) && !(equipmentType instanceof BayWeapon) - && !equipmentType.hasFlag(WeaponType.F_AMS) && !equipmentType.is("Screen Launcher") + && (!equipmentType.hasFlag(WeaponType.F_AMS) || amsAsWeapon) + && !equipmentType.is("Screen Launcher") && !equipmentType.hasFlag(WeaponType.F_C3M) && !equipmentType.hasFlag(WeaponType.F_C3MBS) && !equipmentType.hasFlag(WeaponType.F_INFANTRY_ATTACK); } @@ -53,10 +57,10 @@ public static boolean isWeaponSpecialistValid(EquipmentType equipmentType) { * * @return A list of weapon names from the given Entity that are valid choices for the Weapon Specialist SPA */ - public static List weaponSpecialistValidWeaponNames(Entity entity) { + public static List weaponSpecialistValidWeaponNames(Entity entity, @Nullable GameOptions options) { return entity.getTotalWeaponList().stream() .map(Mounted::getType) - .filter(PilotSPAHelper::isWeaponSpecialistValid) + .filter(mounted -> isWeaponSpecialistValid(mounted, options)) .map(EquipmentType::getName) .distinct() .collect(Collectors.toList()); @@ -64,14 +68,14 @@ public static List weaponSpecialistValidWeaponNames(Entity entity) { /** * Returns a List of weapons from those present on the given Entity that are valid choices for the - * Weapon Specialist SPA. Unlike {@link #weaponSpecialistValidWeaponNames(Entity)}, weapons + * Weapon Specialist SPA. Unlike {@link #weaponSpecialistValidWeaponNames(Entity, GameOptions)}, weapons * appear in this list as often as they are present on the given Entity. * * @return A list of weapons from the given Entity that are valid choices for the Weapon Specialist SPA */ - public static List weaponSpecialistValidWeapons(Entity entity) { + public static List weaponSpecialistValidWeapons(Entity entity, @Nullable GameOptions options) { return entity.getTotalWeaponList().stream() - .filter(PilotSPAHelper::isWeaponSpecialistValid) + .filter(mounted -> isWeaponSpecialistValid(mounted, options)) .collect(Collectors.toList()); }