Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #1031 - Show structure collapse warning when deploying and moving. #4984

Merged
merged 15 commits into from
Dec 30, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions megamek/i18n/megamek/client/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,8 @@ CommonMenuBar.viewToggleSensorRange=Visual & Sensor Ranges
CommonMenuBar.viewToggleSensorRangeToolTip=Outline Visual & Sensor Ranges
CommonMenuBar.viewToggleFiringSolutions=Firing Solutions
CommonMenuBar.viewToggleFiringSolutionsToolTip=During the firing phase, to-hit modifiers for each range bracket will be drawn on units
CommonMenuBar.viewToggleCFWarning=Structure Collapse Warning
CommonMenuBar.viewToggleCFWarningToolTip=Show buildings or bridges that could collapse if entered by selected unit
CommonMenuBar.viewChangeTheme=Change Tileset Theme
CommonMenuBar.viewResetWindowPos=Reset Window Positions
CommonMenuBar.moveLAMmechMode=Transform to mek mode
Expand Down
4 changes: 4 additions & 0 deletions megamek/src/megamek/client/ui/swing/ClientGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public class ClientGUI extends JPanel implements BoardViewListener,
public static final String VIEW_TOGGLE_FOV_DARKEN = "viewToggleFovDarken";
public static final String VIEW_TOGGLE_FOV_HIGHLIGHT = "viewToggleFovHighlight";
public static final String VIEW_TOGGLE_FIRING_SOLUTIONS = "viewToggleFiringSolutions";
public static final String VIEW_TOGGLE_CF_WARNING = "viewToggleCFWarnings";
public static final String VIEW_MOVE_ENV = "viewMovementEnvelope";
public static final String VIEW_TURN_DETAILS_OVERLAY = "viewTurnDetailsOverlay";
public static final String VIEW_MOVE_MOD_ENV = "viewMovModEnvelope";
Expand Down Expand Up @@ -934,6 +935,9 @@ public void actionPerformed(ActionEvent event) {
}
bv.refreshDisplayables();
break;
case VIEW_TOGGLE_CF_WARNING:
ConstructionFactorWarning.handleActionPerformed(client.getGame(), bv);
break;
case VIEW_MOVE_ENV:
if (curPanel instanceof MovementDisplay) {
GUIP.setMoveEnvelope(!GUIP.getMoveEnvelope());
Expand Down
6 changes: 6 additions & 0 deletions megamek/src/megamek/client/ui/swing/CommonMenuBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public class CommonMenuBar extends JMenuBar implements ActionListener, IPreferen
private JCheckBoxMenuItem toggleFovHighlight = new JCheckBoxMenuItem(getString("CommonMenuBar.viewToggleFovHighlight"));
private JCheckBoxMenuItem toggleFovDarken = new JCheckBoxMenuItem(getString("CommonMenuBar.viewToggleFovDarken"));
private JCheckBoxMenuItem toggleFiringSolutions = new JCheckBoxMenuItem(getString("CommonMenuBar.viewToggleFiringSolutions"));
private JCheckBoxMenuItem toggleCFWarning = new JCheckBoxMenuItem(getString("CommonMenuBar.viewToggleCFWarning"));
private JCheckBoxMenuItem viewMovementEnvelope = new JCheckBoxMenuItem(getString("CommonMenuBar.movementEnvelope"));
private JCheckBoxMenuItem viewTurnDetailsOverlay = new JCheckBoxMenuItem(getString("CommonMenuBar.turnDetailsOverlay"));
private JMenuItem viewMovModEnvelope = new JMenuItem(getString("CommonMenuBar.movementModEnvelope"));
Expand Down Expand Up @@ -305,6 +306,10 @@ public CommonMenuBar() {
toggleFiringSolutions.setToolTipText(Messages.getString("CommonMenuBar.viewToggleFiringSolutionsToolTip"));
toggleFiringSolutions.setSelected(GUIP.getFiringSolutions());

initMenuItem(toggleCFWarning, menu, VIEW_TOGGLE_CF_WARNING);
toggleCFWarning.setToolTipText(Messages.getString("CommonMenuBar.viewToggleCFWarningToolTip"));
toggleCFWarning.setSelected(GUIP.getShowCFWarnings());

/* TODO: moveTraitor = createMenuItem(menu, getString("CommonMenuBar.moveTraitor"), MovementDisplay.MOVE_TRAITOR); */

// Create the Help menu
Expand Down Expand Up @@ -479,6 +484,7 @@ private synchronized void updateEnabledStates() {
toggleFovHighlight.setEnabled(isInGameBoardView);
toggleFovDarken.setEnabled(isInGameBoardView);
toggleFiringSolutions.setEnabled(isInGameBoardView);
toggleCFWarning.setEnabled(isInGameBoardView);
viewMovementEnvelope.setEnabled(isInGameBoardView);
viewTurnDetailsOverlay.setEnabled(isInGameBoardView);
viewMovModEnvelope.setEnabled(isInGameBoardView);
Expand Down
12 changes: 12 additions & 0 deletions megamek/src/megamek/client/ui/swing/DeploymentDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ public void selectEntity(int en) {
clientgui.getUnitDisplay().showPanel("movement");
clientgui.getBoardView().setWeaponFieldOfFire(ce().getFacing(), ce().getPosition());
clientgui.getBoardView().setSensorRange(ce(), ce().getPosition());
computeCFWarningHexes(ce());
} else {
disableButtons();
setNextEnabled(true);
Expand All @@ -239,6 +240,17 @@ public void selectEntity(int en) {
}
}

private void computeCFWarningHexes(Entity ce) {
List<Coords> warnList =
ConstructionFactorWarning.findCFWarningsDeployment(
clientgui.getBoardView().game,
ce,
clientgui.getBoardView().game.getBoard());

clientgui.getBoardView().setCFWarningSprites(warnList);

}

/** Enables relevant buttons and sets up for your turn. */
private void beginMyTurn() {
clientgui.maybeShowUnitDisplay();
Expand Down
12 changes: 11 additions & 1 deletion megamek/src/megamek/client/ui/swing/GUIPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ public class GUIPreferences extends PreferenceStoreProxy {
public static final String TEAM_COLORING = "EntityTeamLabelColor";
public static final String FOCUS = "Focus";
public static final String FIRING_SOLUTIONS = "FiringSolutions";
public static final String CONSTRUCTOR_FACTOR_WARNING = "ConstructionFactorWarning";
public static final String MOVE_ENVELOPE = "MoveEnvelope";
public static final String TURN_DETAILS_OVERLAY = "TurnDetailsOverlay";
public static final String FOV_HIGHLIGHT = "FovHighlight";
Expand Down Expand Up @@ -602,6 +603,7 @@ protected GUIPreferences() {
store.setDefault(UNIT_LABEL_BORDER, true);
store.setDefault(UNIT_LABEL_STYLE, LabelDisplayStyle.NICKNAME.name());
store.setDefault(FIRING_SOLUTIONS, true);
store.setDefault(CONSTRUCTOR_FACTOR_WARNING, true);
store.setDefault(GUI_SCALE, 1);
store.setDefault(LOBBY_MEKTABLE_UNIT_WIDTH, 170);
store.setDefault(LOBBY_MEKTABLE_PILOT_WIDTH, 80);
Expand Down Expand Up @@ -1003,6 +1005,10 @@ public boolean getFiringSolutions() {
return store.getBoolean(FIRING_SOLUTIONS);
}

public boolean getShowCFWarnings() {
return store.getBoolean(CONSTRUCTOR_FACTOR_WARNING);
}

public boolean getMoveEnvelope() {
return store.getBoolean(MOVE_ENVELOPE);
}
Expand Down Expand Up @@ -1783,6 +1789,10 @@ public void setFiringSolutions(boolean state) {
store.setValue(FIRING_SOLUTIONS, state);
}

public void setShowCFWarnings(boolean b) {
store.setValue(CONSTRUCTOR_FACTOR_WARNING, b);
}

public void setMoveEnvelope(boolean state) {
store.setValue(MOVE_ENVELOPE, state);
}
Expand Down Expand Up @@ -3141,4 +3151,4 @@ protected Color parseRGB(String text) {
return Color.BLUE;
}
//endregion Colours
}
}
11 changes: 11 additions & 0 deletions megamek/src/megamek/client/ui/swing/MovementDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ public synchronized void selectEntity(int en) {
}
clientgui.getBoardView().clearFieldOfFire();
computeMovementEnvelope(ce);
computeCFWarningHexes(ce);
}

private MegamekButton getBtn(MoveCommand c) {
Expand Down Expand Up @@ -4544,6 +4545,16 @@ && ce().getMovementMode() == EntityMovementMode.TRACKED) {
clientgui.getBoardView().setMovementModifierEnvelope(lpf.getLongestComputedPaths());
}

private void computeCFWarningHexes(Entity ce) {
List<Coords> warnList =
ConstructionFactorWarning.findCFWarningsMovement(
clientgui.getBoardView().game,
ce,
clientgui.getBoardView().game.getBoard());

clientgui.getBoardView().setCFWarningSprites(warnList);
}

//
// ActionListener
//
Expand Down
42 changes: 41 additions & 1 deletion megamek/src/megamek/client/ui/swing/boardview/BoardView.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ public class BoardView extends JPanel implements Scrollable, BoardListener, Mous

private ArrayList<FiringSolutionSprite> firingSprites = new ArrayList<>();

private ArrayList<ConstructionWarningSprite> cfWarningSprites = new ArrayList<>();

private ArrayList<MovementEnvelopeSprite> moveEnvSprites = new ArrayList<>();
private ArrayList<MovementModifierEnvelopeSprite> moveModEnvSprites = new ArrayList<>();

Expand Down Expand Up @@ -1156,6 +1158,12 @@ public synchronized void paintComponent(Graphics g) {
// draw onscreen entities
drawSprites(g, entitySprites);

// draw structure warning in the deployment or movement phases
// draw this before moving entities, so they show up under if overlapped.
if (shouldShowCFWarning()) {
drawSprites(g, cfWarningSprites);
}

// draw moving onscreen entities
drawSprites(g, movingEntitySprites);

Expand Down Expand Up @@ -1184,7 +1192,6 @@ public synchronized void paintComponent(Graphics g) {
}
}


// draw the ruler line
if (rulerStart != null) {
Point start = getCentreHexLocation(rulerStart);
Expand Down Expand Up @@ -2243,6 +2250,12 @@ public BufferedImage getEntireBoardImage(boolean ignoreUnits, boolean useBaseZoo
// draw onscreen entities
drawSprites(boardGraph, entitySprites);

// draw structure collapse warning sprites if in movement or deploy phase.
// draw this before moving entities, so they show up under if overlapped.
if (shouldShowCFWarning()) {
drawSprites(boardGraph, cfWarningSprites);
}

// draw moving onscreen entities
drawSprites(boardGraph, movingEntitySprites);

Expand Down Expand Up @@ -3869,6 +3882,25 @@ public void clearFiringSolutionData() {
repaint();
}

public void setCFWarningSprites(List<Coords> warnList) {
// Clear existing sprites before setting new ones.
clearCFWarningData();

if (warnList == null) {
return;
}

// Loops through list of coordinates, and create new CF warning sprite and add it to the sprites list.
for (Coords c : warnList) {
ConstructionWarningSprite cfws = new ConstructionWarningSprite(this, c);
cfWarningSprites.add(cfws);
}
}

public void clearCFWarningData() {
cfWarningSprites.clear();
}

public void addStrafingCoords(Coords c) {
strafingCoords.add(c);
}
Expand Down Expand Up @@ -5124,6 +5156,7 @@ void clearSprites() {
movementSprites.clear();
fieldOfFireSprites.clear();
sensorRangeSprites.clear();
cfWarningSprites.clear();
}

public synchronized void updateBoard() {
Expand Down Expand Up @@ -6035,6 +6068,10 @@ private void zoom() {
for (FiringSolutionSprite sprite : firingSprites) {
sprite.prepare();
}

for (ConstructionWarningSprite sprite : cfWarningSprites) {
sprite.prepare();
}
this.setSize(boardSize);

clearHexImageCache();
Expand Down Expand Up @@ -6695,4 +6732,7 @@ public boolean shouldShowSensorRange() {
|| game.getPhase().isOffboard());
}

public boolean shouldShowCFWarning() {
return ConstructionFactorWarning.shouldShow(game.getPhase(), GUIP.getShowCFWarnings());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package megamek.client.ui.swing.boardview;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;

import megamek.client.ui.swing.GUIPreferences;
import megamek.client.ui.swing.util.StringDrawer;
import megamek.client.ui.swing.util.UIUtil;
import megamek.common.Coords;

/**
* Represents structure CF warnings for entities during deployment
* and movement phase that will collapse if the entity lands-on
* or is deployed on that structure.
*
* From TW: If a units tonnage exceeds the CF of a building
* or bridge, it will collapse. (Or the sum of tonnage of stacked
* units if multiple units occupy the hex)
*/
public class ConstructionWarningSprite extends HexSprite {

private static final GUIPreferences GUIP = GUIPreferences.getInstance();
private static final int TEXT_SIZE = 30;
private static final Color TEXT_COLOR = new Color(255, 255, 40, 128);
private static final Color OUTLINE_COLOR = new Color(40, 40,40,200);

private static final int HEX_CENTER_X = BoardView.HEX_W / 2;
private static final int HEX_CENTER_Y = BoardView.HEX_H / 2;

//Draw a special character 'warning sign'.
private final StringDrawer xWriter = new StringDrawer("\u26A0")
.at(HEX_CENTER_X, HEX_CENTER_Y)
.color(TEXT_COLOR)
.fontSize(TEXT_SIZE)
.center().outline(OUTLINE_COLOR, 1.5f);

/**
* @param boardView1 - parent BoardView object this sprite will be displayed on.
* @param loc - Hex location coordinates of building or bridge where warning will be visible.
*/
public ConstructionWarningSprite(BoardView boardView1, Coords loc) {
super(boardView1, loc);
}

@Override
public void prepare() {
Graphics2D graph = spriteSetup();
xWriter.draw(graph);
graph.dispose();
}

/*
* Standard Hex Sprite 2D Graphics setup. Creates the context, base hex image
* settings, scale, and fonts.
*/
private Graphics2D spriteSetup() {
updateBounds();
image = createNewHexImage();
Graphics2D graph = (Graphics2D) image.getGraphics();
UIUtil.setHighQualityRendering(graph);
graph.scale(bv.scale, bv.scale);

fontSetup(graph);

return graph;
}

/*
* Sets the font name, style, and size from configured default parameters.
*/
private void fontSetup(Graphics2D graph) {
String fontName = GUIP.getMoveFontType();
int fontStyle = GUIP.getMoveFontStyle();
graph.setFont(new Font(fontName, fontStyle, TEXT_SIZE));
}
}
Loading