diff --git a/megamek/i18n/megamek/client/messages.properties b/megamek/i18n/megamek/client/messages.properties index 8fdaeab24d9..fbb998c5efa 100644 --- a/megamek/i18n/megamek/client/messages.properties +++ b/megamek/i18n/megamek/client/messages.properties @@ -4710,4 +4710,12 @@ Gamemaster.cmd.orbitalbombardment.help=Calls an orbital bombardment on the board Gamemaster.cmd.orbitalbombardment.dmg=Total damage at target hex. Gamemaster.cmd.orbitalbombardment.radius=Radius of the bombardment. Gamemaster.cmd.orbitalbombardment.error.outofbounds=Specified hex is not on the board. -Gamemaster.cmd.orbitalbombardment.success=Orbital bombardment incoming! \ No newline at end of file +Gamemaster.cmd.orbitalbombardment.success=Orbital bombardment incoming! +# Firefight +Gamemaster.cmd.firefight.longName=Firefight +Gamemaster.cmd.firefight.reason=Fire extinguished +Gamemaster.cmd.firefight.help=Extinguishes a fire on the board. +# No Fire +Gamemaster.cmd.nofire.longName=No Fires +Gamemaster.cmd.nofire.help=Extinguishes all fires on the board. + diff --git a/megamek/src/megamek/client/ui/swing/MapMenu.java b/megamek/src/megamek/client/ui/swing/MapMenu.java index 02f40d37980..2511c4bb577 100644 --- a/megamek/src/megamek/client/ui/swing/MapMenu.java +++ b/megamek/src/megamek/client/ui/swing/MapMenu.java @@ -229,17 +229,7 @@ private JMenuItem TargetMenuItem(Targetable t) { JMenuItem item = new JMenuItem(Messages.getString("ClientGUI.targetMenuItem") + t.getDisplayName()); - String targetCode; - - if (t instanceof Entity) { - targetCode = "E|" + ((Entity) t).getId(); - } else if (t instanceof BuildingTarget) { - targetCode = "B|" + t.getPosition().getX() + "|" + t.getPosition().getY() + "|" + t.getTargetType(); - } else if (t instanceof MinefieldTarget) { - targetCode = "M|" + t.getPosition().getX() + "|" + t.getPosition().getY(); - } else { - targetCode = "H|" + t.getPosition().getX() + "|" + t.getPosition().getY() + "|" + t.getTargetType(); - } + String targetCode = getTargetCode(t); item.setActionCommand(targetCode); item.addActionListener(evt -> { @@ -255,6 +245,21 @@ private JMenuItem TargetMenuItem(Targetable t) { return item; } + private static String getTargetCode(Targetable t) { + String targetCode; + + if (t instanceof Entity) { + targetCode = "E|" + ((Entity) t).getId(); + } else if (t instanceof BuildingTarget) { + targetCode = "B|" + t.getPosition().getX() + "|" + t.getPosition().getY() + "|" + t.getTargetType(); + } else if (t instanceof MinefieldTarget) { + targetCode = "M|" + t.getPosition().getX() + "|" + t.getPosition().getY(); + } else { + targetCode = "H|" + t.getPosition().getX() + "|" + t.getPosition().getY() + "|" + t.getTargetType(); + } + return targetCode; + } + private @Nullable JMenuItem createChargeMenuItem() { if (!client.getGame().getEntities(coords).hasNext()) { return null; @@ -403,9 +408,7 @@ private JMenu createSpecialHexDisplayMenu() { */ private JMenu createGamemasterMenu() { JMenu menu = new JMenu(Messages.getString("Gamemaster.Gamemaster")); - if (!client.getLocalPlayer().getGameMaster()) { - return menu; - } else { + if (client.getLocalPlayer().getGameMaster()) { JMenu dmgMenu = new JMenu(Messages.getString("Gamemaster.EditDamage")); JMenu cfgMenu = new JMenu(Messages.getString("Gamemaster.Configure")); JMenu traitorMenu = new JMenu(Messages.getString("Gamemaster.Traitor")); @@ -435,8 +438,8 @@ private JMenu createGamemasterMenu() { menu.addSeparator(); } menu.add(specialCommandsMenu); - return menu; } + return menu; } /** @@ -446,14 +449,16 @@ private JMenu createGamemasterMenu() { private JMenu createGMSpecialCommandsMenu() { JMenu menu = new JMenu(Messages.getString("Gamemaster.SpecialCommands")); List.of( - new KillCommand(null, null), - new OrbitalBombardmentCommand(null, null), new ChangeOwnershipCommand(null, null), + new ChangeWeatherCommand(null, null), new DisasterCommand(null, null), + new KillCommand(null, null), + new FirefightCommand(null, null), new FirestarterCommand(null, null), new FirestormCommand(null, null), - new RemoveSmokeCommand(null, null), - new ChangeWeatherCommand(null, null) + new NoFiresCommand(null, null), + new OrbitalBombardmentCommand(null, null), + new RemoveSmokeCommand(null, null) ).forEach(cmd -> { JMenuItem item = new JMenuItem(cmd.getLongName()); item.addActionListener(evt -> new GamemasterCommandPanel(gui.getFrame(), gui, cmd).setVisible(true)); @@ -1509,9 +1514,7 @@ private void selectTarget() { if (list.size() == 1) { myTarget = selectedEntity = list.firstElement(); - - if (currentPanel instanceof FiringDisplay) { - FiringDisplay panel = (FiringDisplay) currentPanel; + if (currentPanel instanceof FiringDisplay panel) { panel.target(myTarget); } else if (currentPanel instanceof PhysicalDisplay) { ((PhysicalDisplay) currentPanel).target(myTarget); diff --git a/megamek/src/megamek/server/commands/FirefightCommand.java b/megamek/src/megamek/server/commands/FirefightCommand.java new file mode 100644 index 00000000000..956f3508d1b --- /dev/null +++ b/megamek/src/megamek/server/commands/FirefightCommand.java @@ -0,0 +1,77 @@ +/* + * MegaMek - Copyright (c) 2024 - The MegaMek Team. All Rights Reserved. + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megamek.server.commands; + +import megamek.client.ui.Messages; +import megamek.common.Coords; +import megamek.common.Hex; +import megamek.server.Server; +import megamek.server.commands.arguments.Argument; +import megamek.server.commands.arguments.IntegerArgument; +import megamek.server.totalwarfare.TWGameManager; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * The Server Command "/firefight" that will put one hex on fire. + * + * @author Luana Coppio + */ +public class FirefightCommand extends GamemasterServerCommand { + + private static final String FIRESTARTER = "firefight"; + private static final String X = "x"; + private static final String Y = "y"; + private static final String TYPE = "type"; + + public FirefightCommand(Server server, TWGameManager gameManager) { + super(server, + gameManager, + FIRESTARTER, + Messages.getString("Gamemaster.cmd.firefight.help"), + Messages.getString("Gamemaster.cmd.firefight.longName")); + } + + @Override + public List> defineArguments() { + return List.of( + new IntegerArgument(X, Messages.getString("Gamemaster.cmd.x")), + new IntegerArgument(Y, Messages.getString("Gamemaster.cmd.y")) + ); + } + + /** + * Run this command with the arguments supplied + * + * @see ServerCommand#run(int, String[]) + */ + @Override + protected void runAsGM(int connId, Map> args) { + int xArg = (int) args.get(X).getValue() - 1; + int yArg = (int) args.get(Y).getValue() - 1; + firefight(new Coords(xArg, yArg)); + } + + private void firefight(Coords coords) { + try { + Hex hex = gameManager.getGame().getBoard().getHex(coords); + Objects.requireNonNull(hex, "Hex not found."); + gameManager.removeFire(coords, Messages.getString("Gamemaster.cmd.firefight.reason")); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to ignite hex: " + e.getMessage()); + } + } +} diff --git a/megamek/src/megamek/server/commands/NoFiresCommand.java b/megamek/src/megamek/server/commands/NoFiresCommand.java new file mode 100644 index 00000000000..f097ff1fbb2 --- /dev/null +++ b/megamek/src/megamek/server/commands/NoFiresCommand.java @@ -0,0 +1,87 @@ +/* + * MegaMek - Copyright (c) 2024 - The MegaMek Team. All Rights Reserved. + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megamek.server.commands; + +import megamek.client.ui.Messages; +import megamek.common.Coords; +import megamek.common.Hex; +import megamek.server.Server; +import megamek.server.commands.arguments.Argument; +import megamek.server.commands.arguments.IntegerArgument; +import megamek.server.totalwarfare.TWGameManager; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +/** + * The Server Command "/nofires" removes all fires on the board. + * + * @author Luana Coppio + */ +public class NoFiresCommand extends GamemasterServerCommand { + + private final String reason; + + public NoFiresCommand(Server server, TWGameManager gameManager) { + super(server, + gameManager, + "nofires", + Messages.getString("Gamemaster.cmd.nofire.help"), + Messages.getString("Gamemaster.cmd.nofire.longName")); + this.reason = Messages.getString("Gamemaster.cmd.firefight.reason"); + } + + @Override + public List> defineArguments() { + return List.of(); + } + + /** + * Run this command with the arguments supplied + * + * @see ServerCommand#run(int, String[]) + */ + @Override + protected void runAsGM(int connId, Map> args) { + try { + getAllCoords().forEach(this::firefight); + } catch (Exception e) { + logger.error(Messages.getString("Gamemaster.cmd.fire.failed"), e); + server.sendServerChat(connId, Messages.getString("Gamemaster.cmd.fire.failed")); + } + } + + private HashSet getAllCoords() { + var boardHeight = gameManager.getGame().getBoard().getHeight(); + var boardWidth = gameManager.getGame().getBoard().getWidth(); + var coordsSet = new HashSet(); + for (int x = 0; x < boardWidth; x++) { + for (int y = 0; y < boardHeight; y++) { + coordsSet.add(new Coords(x, y)); + } + } + return coordsSet; + } + + private void firefight(Coords coords) { + Hex hex = gameManager.getGame().getBoard().getHex(coords); + if (null == hex) { + // Just ignore null hexes... + // they should not happen, but I don't want to crash the command + return; + } + gameManager.removeFire(coords, reason); + } +} diff --git a/megamek/src/megamek/server/totalwarfare/TWGameManager.java b/megamek/src/megamek/server/totalwarfare/TWGameManager.java index 2ac90e804de..3912a76c7f6 100644 --- a/megamek/src/megamek/server/totalwarfare/TWGameManager.java +++ b/megamek/src/megamek/server/totalwarfare/TWGameManager.java @@ -194,6 +194,8 @@ public List getCommandList(Server server) { commands.add(new ChangeOwnershipCommand(server, this)); commands.add(new DisasterCommand(server, this)); commands.add(new FirestarterCommand(server, this)); + commands.add(new NoFiresCommand(server, this)); + commands.add(new FirefightCommand(server, this)); commands.add(new FirestormCommand(server, this)); commands.add(new RemoveSmokeCommand(server, this)); commands.add(new ChangeWeatherCommand(server, this));