/*
* MegaMek -
* Copyright (C) 2000,2001,2002,2003,2004,2005 Ben Mazur (bmazur@sev.org)
*
* 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.client.ui.AWT;
import java.awt.Button;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.TreeMap;
import java.util.Vector;
import megamek.client.Client;
import megamek.client.event.BoardViewEvent;
import megamek.client.event.BoardViewListener;
import megamek.client.ui.Messages;
import megamek.client.ui.SharedUtility;
import megamek.common.Aero;
import megamek.common.BattleArmor;
import megamek.common.Bay;
import megamek.common.BipedMech;
import megamek.common.Building;
import megamek.common.BuildingTarget;
import megamek.common.Compute;
import megamek.common.Coords;
import megamek.common.Entity;
import megamek.common.EntitySelector;
import megamek.common.GameTurn;
import megamek.common.IEntityMovementMode;
import megamek.common.IEntityMovementType;
import megamek.common.IGame;
import megamek.common.IHex;
import megamek.common.Infantry;
import megamek.common.Jumpship;
import megamek.common.LandAirMech;
import megamek.common.ManeuverType;
import megamek.common.Mech;
import megamek.common.Minefield;
import megamek.common.MiscType;
import megamek.common.Mounted;
import megamek.common.MovePath;
import megamek.common.MoveStep;
import megamek.common.Protomech;
import megamek.common.SpaceStation;
import megamek.common.Tank;
import megamek.common.TargetRoll;
import megamek.common.Targetable;
import megamek.common.TeleMissile;
import megamek.common.Terrains;
import megamek.common.ToHitData;
import megamek.common.VTOL;
import megamek.common.Warship;
import megamek.common.actions.ChargeAttackAction;
import megamek.common.actions.DfaAttackAction;
import megamek.common.actions.RamAttackAction;
import megamek.common.event.GameListener;
import megamek.common.event.GamePhaseChangeEvent;
import megamek.common.event.GameTurnChangeEvent;
public class MovementDisplay extends StatusBarPhaseDisplay implements ActionListener,
DoneButtoned, KeyListener, GameListener, BoardViewListener {
/**
*
*/
private static final long serialVersionUID = 9136822404087057673L;
private static final int NUM_BUTTON_LAYOUTS = 4;
public static final String MOVE_WALK = "moveWalk"; //$NON-NLS-1$
public static final String MOVE_NEXT = "moveNext"; //$NON-NLS-1$
public static final String MOVE_JUMP = "moveJump"; //$NON-NLS-1$
public static final String MOVE_BACK_UP = "moveBackUp"; //$NON-NLS-1$
public static final String MOVE_TURN = "moveTurn"; //$NON-NLS-1$
public static final String MOVE_GET_UP = "moveGetUp"; //$NON-NLS-1$
public static final String MOVE_CHARGE = "moveCharge"; //$NON-NLS-1$
public static final String MOVE_DFA = "moveDFA"; //$NON-NLS-1$
public static final String MOVE_GO_PRONE = "moveGoProne"; //$NON-NLS-1$
public static final String MOVE_FLEE = "moveFlee"; //$NON-NLS-1$
public static final String MOVE_EJECT = "moveEject"; //$NON-NLS-1$
public static final String MOVE_LOAD = "moveLoad"; //$NON-NLS-1$
public static final String MOVE_UNLOAD = "moveUnload"; //$NON-NLS-1$
public static final String MOVE_UNJAM = "moveUnjam"; //$NON-NLS-1$
public static final String MOVE_CLEAR = "moveClear"; //$NON-NLS-1$
public static final String MOVE_CANCEL = "moveCancel"; //$NON-NLS-1$
public static final String MOVE_RAISE_ELEVATION = "moveRaiseElevation"; //$NON-NLS-1$
public static final String MOVE_LOWER_ELEVATION = "moveLowerElevation"; //$NON-NLS-1$
public static final String MOVE_SEARCHLIGHT = "moveSearchlight"; //$NON-NLS-1$
public static final String MOVE_LAY_MINE = "moveLayMine"; //$NON-NLS-1$
public static final String MOVE_HULL_DOWN = "moveHullDown"; //$NON-NLS-1$
public static final String MOVE_CLIMB_MODE = "moveClimbMode"; //$NON-NLS-1$
public static final String MOVE_SWIM = "moveSwim"; //$NON-NLS-1$
public static final String MOVE_DIG_IN = "moveDigIn"; //$NON-NLS-1$
public static final String MOVE_FORTIFY = "moveFortify"; //$NON-NLS-1$
public static final String MOVE_SHAKE_OFF = "moveShakeOff"; //$NON-NLS-1$
public static final String MOVE_MODE_MECH = "moveModeMech"; //$NON-NLS-1$
public static final String MOVE_MODE_AIRMECH = "moveModeAirmech"; //$NON-NLS-1$
public static final String MOVE_MODE_AIRCRAFT = "moveModeAircraft"; //$NON-NLS-1$
public static final String MOVE_RECKLESS = "moveReckless"; //$NON-NLS-1$
public static final String MOVE_CAREFUL_STAND = "moveCarefulStand"; //$NON-NLS-1$
public static final String MOVE_EVADE = "MoveEvade"; //$NON-NLS-1$
// Aero Movement
public static final String MOVE_ACC = "MoveAccelerate"; //$NON-NLS-1$
public static final String MOVE_DEC = "MoveDecelerate"; //$NON-NLS-1$
public static final String MOVE_EVADE_AERO = "MoveEvadeAero"; //$NON-NLS-1$
public static final String MOVE_ACCN = "MoveAccNext"; //$NON-NLS-1$
public static final String MOVE_DECN = "MoveDecNext"; //$NON-NLS-1$
public static final String MOVE_ROLL = "MoveRoll"; //$NON-NLS-1$
public static final String MOVE_LAUNCH = "MoveLaunch"; //$NON-NLS-1$
public static final String MOVE_RECOVER = "MoveRecover"; //$NON-NLS-1$
public static final String MOVE_DUMP = "MoveDump"; //$NON-NLS-1$
public static final String MOVE_RAM = "MoveRam"; //$NON-NLS-1$
public static final String MOVE_HOVER = "MoveHover"; //$NON-NLS-1$
public static final String MOVE_MANEUVER = "MoveManeuver"; //$NON-NLS-1$
public static final String MOVE_JOIN = "MoveJoin"; //$NON-NLS-1$
// Aero Vector Movement
public static final String MOVE_TURN_LEFT = "MoveTurnLeft"; //$NON-NLS-1$
public static final String MOVE_TURN_RIGHT = "MoveTurnRight"; //$NON-NLS-1$
public static final String MOVE_THRUST = "MoveThrust"; //$NON-NLS-1$
public static final String MOVE_YAW = "MoveYaw"; //$NON-NLS-1$
public static final String MOVE_END_OVER = "MoveEndOver"; //$NON-NLS-1$
// parent game
public Client client;
private ClientGUI clientgui;
// buttons
private Panel panButtons;
private Button butWalk;
private Button butJump;
private Button butBackup;
private Button butTurn;
private Button butSwim;
private Button butUp;
private Button butDown;
private Button butCharge;
private Button butDfa;
private Button butRAC;
private Button butFlee;
private Button butEject;
private Button butLoad;
private Button butUnload;
private Button butSpace;
private Button butClear;
private Button butNext;
private Button butDone;
private Button butMore;
private Button butRaise;
private Button butLower;
private Button butSearchlight;
private Button butLayMine;
private Button butHullDown;
private Button butClimbMode;
private Button butDigIn;
private Button butFortify;
private Button butShakeOff;
private Button butReckless;
private Button butEvade;
private Button butAcc;
private Button butDec;
private Button butEvadeAero;
private Button butAccN;
private Button butDecN;
private Button butRoll;
private Button butLaunch;
private Button butRecover;
private Button butDump;
private Button butRam;
private Button butHover;
private Button butManeuver;
private Button butJoin;
private Button butTurnLeft;
private Button butTurnRight;
private Button butThrust;
private Button butYaw;
private Button butEndOver;
private int buttonLayout;
// order of buttons for various entity types
private ArrayList<Button> buttonsMech;
private ArrayList<Button> buttonsTank;
private ArrayList<Button> buttonsVtol;
private ArrayList<Button> buttonsInf;
private ArrayList<Button> buttonsAero;
// let's keep track of what we're moving, too
private int cen = Entity.NONE; // current entity number
private MovePath cmd; // considering movement data
// what "gear" is our mech in?
private int gear;
// is the shift key held?
private boolean shiftheld;
/**
* A local copy of the current entity's loaded units.
*/
private Vector<Entity> loadedUnits = null;
public static final int GEAR_LAND = 0;
public static final int GEAR_BACKUP = 1;
public static final int GEAR_JUMP = 2;
public static final int GEAR_CHARGE = 3;
public static final int GEAR_DFA = 4;
public static final int GEAR_TURN = 5;
public static final int GEAR_SWIM = 6;
public static final int GEAR_RAM = 7;
public static final int GEAR_IMMEL = 8;
public static final int GEAR_SPLIT_S = 9;
/**
* Creates and lays out a new movement phase display for the specified
* client.
*/
public MovementDisplay(ClientGUI clientgui) {
this.clientgui = clientgui;
client = clientgui.getClient();
client.game.addGameListener(this);
gear = MovementDisplay.GEAR_LAND;
shiftheld = false;
clientgui.getBoardView().addBoardViewListener(this);
setupStatusBar(Messages.getString("MovementDisplay.waitingForMovementPhase")); //$NON-NLS-1$
butClear = new Button(Messages.getString("MovementDisplay.butClear")); //$NON-NLS-1$
butClear.addActionListener(this);
butClear.setEnabled(false);
butClear.setActionCommand(MOVE_CLEAR);
butClear.addKeyListener(this);
butWalk = new Button(Messages.getString("MovementDisplay.butWalk")); //$NON-NLS-1$
butWalk.addActionListener(this);
butWalk.setEnabled(false);
butWalk.setActionCommand(MOVE_WALK);
butWalk.addKeyListener(this);
butJump = new Button(Messages.getString("MovementDisplay.butJump")); //$NON-NLS-1$
butJump.addActionListener(this);
butJump.setEnabled(false);
butJump.setActionCommand(MOVE_JUMP);
butJump.addKeyListener(this);
butSwim = new Button(Messages.getString("MovementDisplay.butSwim")); //$NON-NLS-1$
butSwim.addActionListener(this);
butSwim.setEnabled(false);
butSwim.setActionCommand(MOVE_SWIM);
butSwim.addKeyListener(this);
butBackup = new Button(Messages.getString("MovementDisplay.butBackup")); //$NON-NLS-1$
butBackup.addActionListener(this);
butBackup.setEnabled(false);
butBackup.setActionCommand(MOVE_BACK_UP);
butBackup.addKeyListener(this);
butTurn = new Button(Messages.getString("MovementDisplay.butTurn")); //$NON-NLS-1$
butTurn.addActionListener(this);
butTurn.setEnabled(false);
butTurn.setActionCommand(MOVE_TURN);
butTurn.addKeyListener(this);
butUp = new Button(Messages.getString("MovementDisplay.butUp")); //$NON-NLS-1$
butUp.addActionListener(this);
butUp.setEnabled(false);
butUp.setActionCommand(MOVE_GET_UP);
butUp.addKeyListener(this);
butDown = new Button(Messages.getString("MovementDisplay.butDown")); //$NON-NLS-1$
butDown.addActionListener(this);
butDown.setEnabled(false);
butDown.setActionCommand(MOVE_GO_PRONE);
butDown.addKeyListener(this);
butCharge = new Button(Messages.getString("MovementDisplay.butCharge")); //$NON-NLS-1$
butCharge.addActionListener(this);
butCharge.setEnabled(false);
butCharge.setActionCommand(MOVE_CHARGE);
butCharge.addKeyListener(this);
butDfa = new Button(Messages.getString("MovementDisplay.butDfa")); //$NON-NLS-1$
butDfa.addActionListener(this);
butDfa.setEnabled(false);
butDfa.setActionCommand(MOVE_DFA);
butDfa.addKeyListener(this);
butFlee = new Button(Messages.getString("MovementDisplay.butFlee")); //$NON-NLS-1$
butFlee.addActionListener(this);
butFlee.setEnabled(false);
butFlee.setActionCommand(MOVE_FLEE);
butFlee.addKeyListener(this);
butEject = new Button(Messages.getString("MovementDisplay.butEject")); //$NON-NLS-1$
butEject.addActionListener(this);
butEject.setEnabled(false);
butEject.setActionCommand(MOVE_EJECT);
butEject.addKeyListener(this);
butRAC = new Button(Messages.getString("MovementDisplay.butRAC")); //$NON-NLS-1$
butRAC.addActionListener(this);
butRAC.setEnabled(false);
butRAC.setActionCommand(MOVE_UNJAM);
butRAC.addKeyListener(this);
butSearchlight = new Button(Messages.getString("MovementDisplay.butSearchlightOn")); //$NON-NLS-1$
butSearchlight.addActionListener(this);
butSearchlight.setEnabled(false);
butSearchlight.setActionCommand(MOVE_SEARCHLIGHT);
butSearchlight.addKeyListener(this);
butMore = new Button(Messages.getString("MovementDisplay.butMore")); //$NON-NLS-1$
butMore.addActionListener(this);
butMore.setEnabled(false);
butMore.addKeyListener(this);
butNext = new Button(Messages.getString("MovementDisplay.butNext")); //$NON-NLS-1$
butNext.addActionListener(this);
butNext.setEnabled(false);
butNext.setActionCommand(MOVE_NEXT);
butNext.addKeyListener(this);
butDone = new Button(Messages.getString("MovementDisplay.butDone")); //$NON-NLS-1$
butDone.addActionListener(this);
butDone.setEnabled(false);
butDone.addKeyListener(this);
butLoad = new Button(Messages.getString("MovementDisplay.butLoad")); //$NON-NLS-1$
butLoad.addActionListener(this);
butLoad.setEnabled(false);
butLoad.setActionCommand(MOVE_LOAD);
butLoad.addKeyListener(this);
butUnload = new Button(Messages.getString("MovementDisplay.butUnload")); //$NON-NLS-1$
butUnload.addActionListener(this);
butUnload.setEnabled(false);
butUnload.setActionCommand(MOVE_UNLOAD);
butUnload.addKeyListener(this);
butRaise = new Button(Messages.getString("MovementDisplay.butRaise")); //$NON-NLS-1$
butRaise.addActionListener(this);
butRaise.setEnabled(false);
butRaise.setActionCommand(MOVE_RAISE_ELEVATION);
butRaise.addKeyListener(this);
butLower = new Button(Messages.getString("MovementDisplay.butLower")); //$NON-NLS-1$
butLower.addActionListener(this);
butLower.setEnabled(false);
butLower.setActionCommand(MOVE_LOWER_ELEVATION);
butLower.addKeyListener(this);
butLayMine = new Button(Messages.getString("MovementDisplay.butLayMine")); //$NON-NLS-1$
butLayMine.addActionListener(this);
butLayMine.setEnabled(false);
butLayMine.setActionCommand(MOVE_LAY_MINE);
butLayMine.addKeyListener(this);
butHullDown = new Button(Messages.getString("MovementDisplay.butHullDown")); //$NON-NLS-1$
butHullDown.addActionListener(this);
butHullDown.setEnabled(false);
butHullDown.setActionCommand(MOVE_HULL_DOWN);
butHullDown.addKeyListener(this);
butClimbMode = new Button(Messages.getString("MovementDisplay.butClimbMode")); //$NON-NLS-1$
butClimbMode.addActionListener(this);
butClimbMode.setEnabled(false);
butClimbMode.setActionCommand(MOVE_CLIMB_MODE);
butClimbMode.addKeyListener(this);
butDigIn = new Button(Messages.getString("MovementDisplay.butDigIn")); //$NON-NLS-1$
butDigIn.addActionListener(this);
butDigIn.setEnabled(false);
butDigIn.setActionCommand(MOVE_DIG_IN);
butDigIn.addKeyListener(this);
butFortify = new Button(Messages.getString("MovementDisplay.butFortify")); //$NON-NLS-1$
butFortify.addActionListener(this);
butFortify.setEnabled(false);
butFortify.setActionCommand(MOVE_FORTIFY);
butFortify.addKeyListener(this);
butShakeOff = new Button(Messages.getString("MovementDisplay.butShakeOff")); //$NON-NLS-1$
butShakeOff.addActionListener(this);
butShakeOff.setEnabled(false);
butShakeOff.setActionCommand(MOVE_SHAKE_OFF);
butShakeOff.addKeyListener(this);
butReckless = new Button(Messages.getString("MovementDisplay.butReckless")); //$NON-NLS-1$
butReckless.addActionListener(this);
butReckless.setEnabled(false);
butReckless.setActionCommand(MOVE_RECKLESS);
butReckless.addKeyListener(this);
butEvade = new Button(Messages.getString("MovementDisplay.butEvade")); //$NON-NLS-1$
butEvade.addActionListener(this);
butEvade.setEnabled(false);
butEvade.setActionCommand(MOVE_EVADE);
butEvade.addKeyListener(this);
butAcc = new Button(Messages.getString("MovementDisplay.butAcc")); //$NON-NLS-1$
butAcc.addActionListener(this);
butAcc.setEnabled(false);
butAcc.setActionCommand(MOVE_ACC);
butAcc.addKeyListener(this);
butDec = new Button(Messages.getString("MovementDisplay.butDec")); //$NON-NLS-1$
butDec.addActionListener(this);
butDec.setEnabled(false);
butDec.setActionCommand(MOVE_DEC);
butDec.addKeyListener(this);
butAccN = new Button(Messages.getString("MovementDisplay.butAccN")); //$NON-NLS-1$
butAccN.addActionListener(this);
butAccN.setEnabled(false);
butAccN.setActionCommand(MOVE_ACCN);
butAccN.addKeyListener(this);
butDecN = new Button(Messages.getString("MovementDisplay.butDecN")); //$NON-NLS-1$
butDecN.addActionListener(this);
butDecN.setEnabled(false);
butDecN.setActionCommand(MOVE_DECN);
butDecN.addKeyListener(this);
butEvadeAero = new Button(Messages.getString("MovementDisplay.butEvadeAero")); //$NON-NLS-1$
butEvadeAero.addActionListener(this);
butEvadeAero.setEnabled(false);
butEvadeAero.setActionCommand(MOVE_EVADE_AERO);
butEvadeAero.addKeyListener(this);
butRoll = new Button(Messages.getString("MovementDisplay.butRoll")); //$NON-NLS-1$
butRoll.addActionListener(this);
butRoll.setEnabled(false);
butRoll.setActionCommand(MOVE_ROLL);
butRoll.addKeyListener(this);
butLaunch = new Button(Messages.getString("MovementDisplay.butLaunch")); //$NON-NLS-1$
butLaunch.addActionListener(this);
butLaunch.setEnabled(false);
butLaunch.setActionCommand(MOVE_LAUNCH);
butLaunch.addKeyListener(this);
butRecover = new Button(Messages.getString("MovementDisplay.butRecover")); //$NON-NLS-1$
butRecover.addActionListener(this);
butRecover.setEnabled(false);
butRecover.setActionCommand(MOVE_RECOVER);
butRecover.addKeyListener(this);
butDump = new Button(Messages.getString("MovementDisplay.butDump")); //$NON-NLS-1$
butDump.addActionListener(this);
butDump.setEnabled(false);
butDump.setActionCommand(MOVE_DUMP);
butDump.addKeyListener(this);
butRam = new Button(Messages.getString("MovementDisplay.butRam")); //$NON-NLS-1$
butRam.addActionListener(this);
butRam.setEnabled(false);
butRam.setActionCommand(MOVE_RAM);
butRam.addKeyListener(this);
butHover = new Button(Messages.getString("MovementDisplay.butHover")); //$NON-NLS-1$
butHover.addActionListener(this);
butHover.setEnabled(false);
butHover.setActionCommand(MOVE_HOVER);
butHover.addKeyListener(this);
butManeuver = new Button(Messages.getString("MovementDisplay.butManeuver")); //$NON-NLS-1$
butManeuver.addActionListener(this);
butManeuver.setEnabled(false);
butManeuver.setActionCommand(MOVE_MANEUVER);
butManeuver.addKeyListener(this);
butJoin = new Button(Messages.getString("MovementDisplay.butJoin")); //$NON-NLS-1$
butJoin.addActionListener(this);
butJoin.setEnabled(false);
butJoin.setActionCommand(MOVE_JOIN);
butJoin.addKeyListener(this);
butTurnLeft = new Button(Messages.getString("MovementDisplay.butTurnLeft")); //$NON-NLS-1$
butTurnLeft.addActionListener(this);
butTurnLeft.setEnabled(false);
butTurnLeft.setActionCommand(MOVE_TURN_LEFT);
butTurnLeft.addKeyListener(this);
butTurnRight = new Button(Messages.getString("MovementDisplay.butTurnRight")); //$NON-NLS-1$
butTurnRight.addActionListener(this);
butTurnRight.setEnabled(false);
butTurnRight.setActionCommand(MOVE_TURN_RIGHT);
butTurnRight.addKeyListener(this);
butThrust = new Button(Messages.getString("MovementDisplay.butThrust")); //$NON-NLS-1$
butThrust.addActionListener(this);
butThrust.setEnabled(false);
butThrust.setActionCommand(MOVE_THRUST);
butThrust.addKeyListener(this);
butYaw = new Button(Messages.getString("MovementDisplay.butYaw")); //$NON-NLS-1$
butYaw.addActionListener(this);
butYaw.setEnabled(false);
butYaw.setActionCommand(MOVE_YAW);
butYaw.addKeyListener(this);
butEndOver = new Button(Messages.getString("MovementDisplay.butEndOver")); //$NON-NLS-1$
butEndOver.addActionListener(this);
butEndOver.setEnabled(false);
butEndOver.setActionCommand(MOVE_END_OVER);
butEndOver.addKeyListener(this);
butSpace = new Button(".");
butSpace.setEnabled(false);
butSpace.addKeyListener(this);
// add buttons to the lists, except space, more & next
buttonsMech = new ArrayList<Button>(22);
buttonsMech.add(butWalk);
buttonsMech.add(butJump);
buttonsMech.add(butBackup);
buttonsMech.add(butTurn);
buttonsMech.add(butUp);
buttonsMech.add(butDown);
buttonsMech.add(butCharge);
buttonsMech.add(butDfa);
buttonsMech.add(butLoad);
buttonsMech.add(butUnload);
buttonsMech.add(butClimbMode);
buttonsMech.add(butSearchlight);
buttonsMech.add(butHullDown);
buttonsMech.add(butSwim);
buttonsMech.add(butEvade);
buttonsMech.add(butReckless);
buttonsMech.add(butEject);
buttonsMech.add(butFlee);
buttonsMech.add(butRAC);
// these are last, they won't be used by mechs
buttonsMech.add(butFortify);
buttonsMech.add(butLayMine);
buttonsMech.add(butLower);
buttonsMech.add(butRaise);
buttonsTank = new ArrayList<Button>(22);
buttonsTank.add(butWalk);
buttonsTank.add(butBackup);
buttonsTank.add(butTurn);
buttonsTank.add(butLoad);
buttonsTank.add(butUnload);
buttonsTank.add(butCharge);
buttonsTank.add(butClimbMode);
buttonsTank.add(butSearchlight);
buttonsTank.add(butHullDown);
buttonsTank.add(butSwim);
buttonsTank.add(butEvade);
buttonsTank.add(butReckless);
buttonsTank.add(butEject);
buttonsTank.add(butFlee);
buttonsTank.add(butRAC);
buttonsTank.add(butLayMine);
buttonsTank.add(butShakeOff);
// these are last, they won't be used by tanks
buttonsTank.add(butUp);
buttonsTank.add(butDown);
buttonsTank.add(butJump);
buttonsTank.add(butDigIn);
buttonsTank.add(butLower);
buttonsTank.add(butRaise);
buttonsVtol = new ArrayList<Button>(22);
buttonsVtol.add(butWalk);
buttonsVtol.add(butBackup);
buttonsVtol.add(butLower);
buttonsVtol.add(butRaise);
buttonsVtol.add(butTurn);
buttonsVtol.add(butLoad);
buttonsVtol.add(butUnload);
buttonsVtol.add(butSearchlight);
buttonsVtol.add(butEvade);
buttonsVtol.add(butReckless);
buttonsVtol.add(butEject);
buttonsVtol.add(butFlee);
buttonsVtol.add(butRAC);
buttonsVtol.add(butShakeOff);
// these are last, they won't be used by vtol
buttonsVtol.add(butLayMine);
buttonsVtol.add(butSwim);
buttonsVtol.add(butClimbMode);
buttonsVtol.add(butCharge);
buttonsVtol.add(butDfa);
buttonsVtol.add(butUp);
buttonsVtol.add(butDown);
buttonsVtol.add(butJump);
buttonsVtol.add(butDigIn);
buttonsInf = new ArrayList<Button>(22);
buttonsInf.add(butWalk);
buttonsInf.add(butJump);
buttonsInf.add(butLower);
buttonsInf.add(butRaise);
buttonsInf.add(butTurn);
buttonsInf.add(butClimbMode);
buttonsInf.add(butSearchlight);
buttonsInf.add(butEject);
buttonsInf.add(butFlee);
buttonsInf.add(butRAC);
buttonsInf.add(butLayMine);
buttonsInf.add(butSwim);
buttonsInf.add(butDigIn);
buttonsInf.add(butFortify);
buttonsInf.add(butClear);
// these are last, they won't be used by infantry
buttonsInf.add(butLoad);
buttonsInf.add(butUnload);
buttonsInf.add(butBackup);
buttonsInf.add(butHullDown);
buttonsInf.add(butCharge);
buttonsInf.add(butDfa);
buttonsInf.add(butUp);
buttonsInf.add(butDown);
buttonsAero = new ArrayList<Button>(22);
if (!client.game.useVectorMove()) {
buttonsAero.add(butWalk);
buttonsAero.add(butAcc);
buttonsAero.add(butDec);
buttonsAero.add(butTurn);
buttonsAero.add(butAccN);
buttonsAero.add(butDecN);
buttonsAero.add(butRoll);
buttonsAero.add(butEvadeAero);
buttonsAero.add(butRam);
buttonsAero.add(butLower);
buttonsAero.add(butRaise);
buttonsAero.add(butManeuver);
buttonsAero.add(butEject);
buttonsAero.add(butFlee);
buttonsAero.add(butLaunch);
buttonsAero.add(butRecover);
buttonsAero.add(butJoin);
buttonsAero.add(butHover);
buttonsAero.add(butRAC);
buttonsAero.add(butDump);
// not used
buttonsAero.add(butHullDown);
buttonsAero.add(butShakeOff);
} else {
buttonsAero.add(butThrust);
buttonsAero.add(butTurnLeft);
buttonsAero.add(butTurnRight);
buttonsAero.add(butEvadeAero);
buttonsAero.add(butRoll);
buttonsAero.add(butYaw);
buttonsAero.add(butEndOver);
buttonsAero.add(butRam);
buttonsAero.add(butEject);
buttonsAero.add(butFlee);
buttonsAero.add(butLaunch);
buttonsAero.add(butRecover);
buttonsAero.add(butJoin);
buttonsAero.add(butRAC);
buttonsAero.add(butDump);
// not used
buttonsAero.add(butUp);
buttonsAero.add(butDown);
buttonsAero.add(butJump);
buttonsAero.add(butDigIn);
buttonsAero.add(butFortify);
buttonsAero.add(butHullDown);
buttonsAero.add(butShakeOff);
}
// TODO: allow Aeros to taxi if on the ground
// layout button grid
panButtons = new Panel();
buttonLayout = 0;
setupButtonPanel();
// layout screen
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
c.insets = new Insets(1, 1, 1, 1);
// c.gridwidth = GridBagConstraints.REMAINDER;
// addBag(clientgui.bv, gridbag, c);
// c.weightx = 1.0; c.weighty = 0;
// c.gridwidth = 1;
// addBag(client.cb.getComponent(), gridbag, c);
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 0.0;
c.weighty = 0.0;
addBag(panButtons, gridbag, c);
c.weightx = 1.0;
c.weighty = 0.0;
c.gridwidth = GridBagConstraints.REMAINDER;
addBag(panStatus, gridbag, c);
clientgui.bv.addKeyListener(this);
addKeyListener(this);
}
private void addBag(Component comp, GridBagLayout gridbag, GridBagConstraints c) {
gridbag.setConstraints(comp, c);
add(comp);
comp.addKeyListener(this);
}
private void setupButtonPanel() {
panButtons.removeAll();
panButtons.setLayout(new GridLayout(0, 8));
// choose button order based on entity type
ArrayList<Button> buttonList = buttonsMech;
final Entity ce = ce();
if (ce != null) {
if (ce instanceof Infantry) {
buttonList = buttonsInf;
} else if (ce instanceof VTOL) {
buttonList = buttonsVtol;
} else if (ce instanceof Tank) {
buttonList = buttonsTank;
} else if (ce instanceof Aero) {
buttonList = buttonsAero;
}
}
// should this layout be skipped? (if nothing enabled)
boolean ok = false;
while (!ok && (buttonLayout != 0)) {
for (int i = buttonLayout * 6; (i < (buttonLayout + 1) * 6) && (i < buttonList.size()); i++) {
if (buttonList.get(i).isEnabled()) {
ok = true;
break;
}
}
if (!ok) {
// skip as nothing was enabled
buttonLayout++;
if (buttonLayout * 6 >= buttonList.size()) {
buttonLayout = 0;
}
}
}
panButtons.add(butNext);
for (int i = buttonLayout * 6; (i < (buttonLayout + 1) * 6) && (i < buttonList.size()); i++) {
panButtons.add(buttonList.get(i));
}
panButtons.add(butMore);
panButtons.validate();
}
/**
* Selects an entity, by number, for movement.
*/
public synchronized void selectEntity(int en) {
final Entity ce = client.game.getEntity(en);
// hmm, sometimes this gets called when there's no ready entities?
if (ce == null) {
System.err.println("MovementDisplay: tried to select non-existant entity: " + en); //$NON-NLS-1$
return;
}
cen = en;
clientgui.setSelectedEntityNum(en);
clearAllMoves();
updateButtons();
// Update the menu bar.
clientgui.getMenuBar().setEntity(ce);
clientgui.getBoardView().highlight(ce.getPosition());
clientgui.getBoardView().select(null);
clientgui.getBoardView().cursor(null);
clientgui.mechD.displayEntity(ce);
clientgui.mechD.showPanel("movement"); //$NON-NLS-1$
if (!clientgui.bv.isMovingUnits()) {
clientgui.bv.centerOnHex(ce.getPosition());
}
}
/**
* Sets the buttons to their proper states
*/
private void updateButtons() {
final Entity ce = ce();
final boolean isMech = (ce instanceof Mech);
final boolean isInfantry = (ce instanceof Infantry);
//final boolean isProtomech = (ce instanceof Protomech);
final boolean isAero = (ce instanceof Aero);
// ^-- I suppose these should really be methods, a-la
// Entity.canCharge(), Entity.canDFA()...
setWalkEnabled(!ce.isImmobile()
&& ((ce.getWalkMP() > 0) || (ce.getRunMP() > 0)) && !ce.isStuck());
setJumpEnabled(!isAero && !ce.isImmobile() && (ce.getJumpMP() > 0) && !(ce.isStuck() && !ce.canUnstickByJumping()));
setSwimEnabled(!isAero && !ce.isImmobile() && ce.hasUMU() && client.game.getBoard().getHex(ce.getPosition()).containsTerrain(Terrains.WATER));
setBackUpEnabled(butWalk.isEnabled() && !isAero);
setChargeEnabled(ce.canCharge());
setDFAEnabled(ce.canDFA());
setRamEnabled(ce.canRam());
if (isInfantry) {
if (client.game.containsMinefield(ce.getPosition())) {
setClearEnabled(true);
} else {
setClearEnabled(false);
}
} else {
setClearEnabled(false);
}
if ((ce.getMovementMode() == IEntityMovementMode.HYDROFOIL) || (ce.getMovementMode() == IEntityMovementMode.NAVAL) || (ce.getMovementMode() == IEntityMovementMode.SUBMARINE) || (ce.getMovementMode() == IEntityMovementMode.INF_UMU) || (ce.getMovementMode() == IEntityMovementMode.VTOL) || (ce.getMovementMode() == IEntityMovementMode.AIRMECH) || (ce.getMovementMode() == IEntityMovementMode.AEROSPACE) || (ce.getMovementMode() == IEntityMovementMode.BIPED_SWIM) || (ce.getMovementMode() == IEntityMovementMode.QUAD_SWIM)) {
butClimbMode.setEnabled(false);
} else {
butClimbMode.setEnabled(true);
}
if (isInfantry) {
butDigIn.setEnabled(true);
butFortify.setEnabled(true);
} else {
butDigIn.setEnabled(false);
butFortify.setEnabled(false);
}
setTurnEnabled(!ce.isImmobile() && !ce.isStuck() && ((ce.getWalkMP() > 0) || (ce.getJumpMP() > 0)));
updateProneButtons();
updateRACButton();
updateSearchlightButton();
updateLoadButtons();
updateElevationButtons();
setEvadeEnabled((isMech || (ce instanceof Tank)) && client.game.getOptions().booleanOption("tacops_evade"));
updateRecoveryButton();
updateJoinButton();
updateDumpButton();
if (ce instanceof Aero) {
butThrust.setEnabled(true);
butYaw.setEnabled(true);
butEndOver.setEnabled(true);
butTurnLeft.setEnabled(true);
butTurnRight.setEnabled(true);
setEvadeAeroEnabled(true);
setEjectEnabled(true);
// no turning for spheroids in atmosphere
if ((((Aero) ce).isSpheroid() || client.game.getPlanetaryConditions().isVacuum())
&& client.game.getBoard().inAtmosphere()) {
setTurnEnabled(false);
}
//jumpships and space stations can turn under different conditions
if((ce instanceof Jumpship) && !(ce instanceof Warship) && !(ce instanceof SpaceStation)) {
setTurnEnabled(true);
}
if((ce instanceof SpaceStation) && (ce.getRunMP() > 0)) {
setTurnEnabled(true);
}
}
updateSpeedButtons();
updateThrustButton();
updateRollButton();
checkFuel();
checkOOC();
checkAtmosphere();
updateFleeButton();
updateLaunchButton();
updateRecklessButton();
updateHoverButton();
updateManeuverButton();
if (isInfantry && ce.hasWorkingMisc(MiscType.F_TOOLS, MiscType.S_VIBROSHOVEL)) {
butFortify.setEnabled(true);
} else {
butFortify.setEnabled(false);
}
if (isInfantry && client.game.getOptions().booleanOption("tacops_dig_in")) {
butDigIn.setEnabled(true);
} else {
butDigIn.setEnabled(false);
}
butShakeOff.setEnabled((ce instanceof Tank) && (ce.getSwarmAttackerId() != Entity.NONE));
setLayMineEnabled(ce.canLayMine());
setFleeEnabled(ce.canFlee());
if (client.game.getOptions().booleanOption("vehicles_can_eject")) { //$NON-NLS-1$
setEjectEnabled((!isInfantry) && !(isMech && (((Mech) ce).getCockpitType() == Mech.COCKPIT_TORSO_MOUNTED)) && ce.isActive());
} else {
setEjectEnabled(isMech && (((Mech) ce).getCockpitType() != Mech.COCKPIT_TORSO_MOUNTED) && ce.isActive());
}
setupButtonPanel();
// handle land air mech transformations
updateTransformationButtons(ce);
}
/**
* This funtcion is called to update the transformation buttons.
*
* @param ce
* the current entity
*/
private void updateTransformationButtons(Entity ce) {
if (ce instanceof LandAirMech) {
final LandAirMech lam = (LandAirMech) ce;
setLAMmechModeEnabled(lam.canConvertToMech());
setLAMairmechModeEnabled(lam.canConvertToAirmech());
setLAMaircraftModeEnabled(lam.canConvertToAircraft());
} else {
setLAMmechModeEnabled(false);
setLAMairmechModeEnabled(false);
setLAMaircraftModeEnabled(false);
}
}
/**
* Enables relevant buttons and sets up for your turn.
*/
private void beginMyTurn() {
setStatusBarText(Messages.getString("MovementDisplay.its_your_turn")); //$NON-NLS-1$
selectEntity(client.getFirstEntityNum());
butDone.setLabel(Messages.getString("MovementDisplay.Done")); //$NON-NLS-1$
butDone.setEnabled(true);
setNextEnabled(true);
butMore.setEnabled(true);
if (!clientgui.bv.isMovingUnits()) {
clientgui.setDisplayVisible(true);
}
}
/**
* Clears out old movement data and disables relevant buttons.
*/
private synchronized void endMyTurn() {
final Entity ce = ce();
// end my turn, then.
disableButtons();
Entity next = client.game.getNextEntity(client.game.getTurnIndex());
if ((IGame.Phase.PHASE_MOVEMENT == client.game.getPhase()) && (null != next) && (null != ce) && (next.getOwnerId() != ce.getOwnerId())) {
clientgui.setDisplayVisible(false);
}
cen = Entity.NONE;
clientgui.getBoardView().select(null);
clientgui.getBoardView().highlight(null);
clientgui.getBoardView().cursor(null);
clientgui.bv.clearMovementData();
}
/**
* Disables all buttons in the interface
*/
private void disableButtons() {
setWalkEnabled(false);
setJumpEnabled(false);
setBackUpEnabled(false);
setTurnEnabled(false);
setFleeEnabled(false);
setEjectEnabled(false);
setUnjamEnabled(false);
setSearchlightEnabled(false, false);
setGetUpEnabled(false);
setGoProneEnabled(false);
setChargeEnabled(false);
setDFAEnabled(false);
setNextEnabled(false);
butMore.setEnabled(false);
butDone.setEnabled(false);
setLoadEnabled(false);
setUnloadEnabled(false);
setClearEnabled(false);
setHullDownEnabled(false);
setSwimEnabled(false);
setEvadeEnabled(false);
setAccEnabled(false);
setDecEnabled(false);
setEvadeAeroEnabled(false);
setAccNEnabled(false);
setDecNEnabled(false);
setRollEnabled(false);
setLaunchEnabled(false);
setThrustEnabled(false);
setYawEnabled(false);
setEndOverEnabled(false);
setTurnLeftEnabled(false);
setTurnRightEnabled(false);
setDumpEnabled(false);
setRamEnabled(false);
setHoverEnabled(false);
setManeuverEnabled(false);
setRecklessEnabled(false);
setJoinEnabled(false);
}
/**
* Clears out the curently selected movement data and resets it.
*/
private void clearAllMoves() {
final Entity ce = ce();
// switch back from swimming to normal mode.
if (ce.getMovementMode() == IEntityMovementMode.BIPED_SWIM) {
ce.setMovementMode(IEntityMovementMode.BIPED);
} else if (ce.getMovementMode() == IEntityMovementMode.QUAD_SWIM) {
ce.setMovementMode(IEntityMovementMode.QUAD);
}
// clear board cursors
clientgui.getBoardView().select(null);
clientgui.getBoardView().cursor(null);
// create new current and considered paths
cmd = new MovePath(client.game, ce);
// set to "walk," or the equivalent
gear = MovementDisplay.GEAR_LAND;
// update some GUI elements
clientgui.bv.clearMovementData();
butDone.setLabel(Messages.getString("MovementDisplay.Done")); //$NON-NLS-1$
updateProneButtons();
updateRACButton();
updateSearchlightButton();
updateElevationButtons();
updateFleeButton();
updateLaunchButton();
updateRecklessButton();
updateHoverButton();
updateManeuverButton();
loadedUnits = ce.getLoadedUnits();
updateLoadButtons();
updateElevationButtons();
updateRecoveryButton();
updateJoinButton();
updateSpeedButtons();
updateThrustButton();
updateRollButton();
checkFuel();
checkOOC();
checkAtmosphere();
}
private void removeLastStep() {
cmd.removeLastStep();
if (cmd.length() == 0) {
clearAllMoves();
} else {
clientgui.bv.drawMovementData(ce(), cmd);
// Set the button's label to "Done"
// if the entire move is impossible.
MovePath possible = cmd.clone();
possible.clipToPossible();
if (possible.length() == 0) {
butDone.setLabel(Messages.getString("MovementDisplay.Done")); //$NON-NLS-1$
}
}
}
/**
* Sends a data packet indicating the chosen movement.
*/
private synchronized void moveTo(MovePath md) {
final Entity ce = ce();
boolean dontCheckPSR = false;
if (ce instanceof Aero) {
Aero a = (Aero) ce;
// first check for stalling
if (client.game.getBoard().inAtmosphere() && !a.isVSTOL() && !a.isSpheroid() && !client.game.getPlanetaryConditions().isVacuum()
&& (((md == null) && (a.getCurrentVelocity() == 0)) || ((md != null) && (md.getFinalVelocity() == 0)))) {
// add a stall to the movement path
md.addStep(MovePath.STEP_STALL);
}
// should check to see if md is null. If so I need to check and see
// if the units
// current velocity is zero
if (md != null) {
boolean isRamming = false;
if ((md.getLastStep() != null) && (md.getLastStep().getType() == MovePath.STEP_RAM)) {
isRamming = true;
}
// if using advanced movement then I need to add on movement
// steps
// to get the vessel from point a to point b
// if the unit is ramming then this is already done
if (client.game.useVectorMove() && !isRamming) {
// get rid of any illegal moves or the rest won't be added
md.clipToPossible();
md = addSteps(md, ce);
}
// check to see if the unit is out of control. If so, then set
// up a new
// move path for them.
// the same should be true if the unit is shutdown or the pilot
// is unconscious
if (!client.game.useVectorMove() && (a.isOutControlTotal() || a.isShutDown() || a.getCrew().isUnconscious())) {
MovePath oldmd = md;
dontCheckPSR = true;
md = new MovePath(client.game, ce);
int vel = a.getCurrentVelocity();
// need to check for stall here as well
if ((vel == 0) && !(a.isSpheroid() || client.game.getPlanetaryConditions().isVacuum()) && client.game.getBoard().inAtmosphere() && !a.isVSTOL()) {
// add a stall to the movement path
md.addStep(MovePath.STEP_STALL);
}
while (vel > 0) {
// check to see if the unit is currently on a border
// and facing a direction that would indicate leaving
// the map
Coords position = a.getPosition();
int facing = a.getFacing();
MoveStep step = md.getLastStep();
if (step != null) {
position = step.getPosition();
facing = step.getFacing();
}
boolean evenx = (position.x % 2) == 0;
if ((((position.x == 0) && ((facing == 5) || (facing == 4))) || ((position.x == client.game.getBoard().getWidth() - 1) && ((facing == 1) || (facing == 2))) || ((position.y == 0) && ((facing == 1) || (facing == 5) || (facing == 0)) && evenx) || ((position.y == 0) && (facing == 0)) || ((position.y == client.game.getBoard().getHeight() - 1) && ((facing == 2) || (facing == 3) || (facing == 4)) && !evenx) || ((position.y == client.game.getBoard().getHeight() - 1) && (facing == 3)))) {
// then this birdie go bye-bye
// set the conditions for removal
md.addStep(MovePath.STEP_OFF);
vel = 0;
} else {
if (a.isRandomMove()) {
int roll = Compute.d6(1);
switch (roll) {
case 1:
md.addStep(MovePath.STEP_FORWARDS);
md.addStep(MovePath.STEP_TURN_LEFT);
md.addStep(MovePath.STEP_TURN_LEFT);
case 2:
md.addStep(MovePath.STEP_FORWARDS);
md.addStep(MovePath.STEP_TURN_LEFT);
case 3:
case 4:
md.addStep(MovePath.STEP_FORWARDS);
case 5:
md.addStep(MovePath.STEP_FORWARDS);
md.addStep(MovePath.STEP_TURN_RIGHT);
case 6:
md.addStep(MovePath.STEP_FORWARDS);
md.addStep(MovePath.STEP_TURN_RIGHT);
md.addStep(MovePath.STEP_TURN_RIGHT);
}
} else {
md.addStep(MovePath.STEP_FORWARDS);
}
vel--;
}
}
// check to see if old movement path contained a launch and
// we are still on the board
if (oldmd.contains(MovePath.STEP_LAUNCH) && !md.contains(MovePath.STEP_OFF)) {
// since launches have to be the last step
MoveStep lastStep = oldmd.getLastStep();
if (lastStep.getType() == MovePath.STEP_LAUNCH) {
md.addStep(lastStep.getType(), lastStep.getLaunched());
}
}
} else {
// I think this should be ok now
md.clipToPossible();
// check to see if velocity left is zero
MoveStep step = md.getLastStep();
if (step != null) {
if ((step.getVelocityLeft() > 0) && !client.game.useVectorMove() && (step.getType() != MovePath.STEP_FLEE)) {
// pop up some dialog telling the unit that it did
// not spend enough
String title = Messages.getString("MovementDisplay.VelocityLeft.title"); //$NON-NLS-1$
String body = Messages.getString("MovementDisplay.VelocityLeft.message"); //$NON-NLS-1$
clientgui.doAlertDialog(title, body);
return;
}
} else {
// if the step is null then the unit didn't move. Make
// sure velocity is zero
if ((a.getCurrentVelocity() > 0) && !client.game.useVectorMove()) {
// pop up some dialog telling the unit that it did
// not spend enough
String title = Messages.getString("MovementDisplay.VelocityLeft.title"); //$NON-NLS-1$
String body = Messages.getString("MovementDisplay.VelocityLeft.message"); //$NON-NLS-1$
clientgui.doAlertDialog(title, body);
return;
}
}
}
// check for G-forces (not for vectored movement)
String check = SharedUtility.doThrustCheck(md);
if (!client.game.useVectorMove() && (check.length() > 0) && GUIPreferences.getInstance().getNagForPSR()) {
ConfirmDialog nag = new ConfirmDialog(clientgui.frame, Messages.getString("MovementDisplay.areYouSure"), //$NON-NLS-1$
Messages.getString("MovementDisplay.ConfirmPilotingRoll") + //$NON-NLS-1$
check, true);
nag.setVisible(true);
if (nag.getAnswer()) {
// do they want to be bothered again?
if (!nag.getShowAgain()) {
GUIPreferences.getInstance().setNagForPSR(false);
}
} else {
return;
}
}
}
}
md.clipToPossible();
if ((md.length() == 0) && GUIPreferences.getInstance().getNagForNoAction()) {
// Hmm....no movement steps, comfirm this action
String title = Messages.getString("MovementDisplay.ConfirmNoMoveDlg.title"); //$NON-NLS-1$
String body = Messages.getString("MovementDisplay.ConfirmNoMoveDlg.message"); //$NON-NLS-1$
ConfirmDialog response = clientgui.doYesNoBotherDialog(title, body);
if (!response.getShowAgain()) {
GUIPreferences.getInstance().setNagForNoAction(false);
}
if (!response.getAnswer()) {
return;
}
}
if (md.hasActiveMASC() && GUIPreferences.getInstance().getNagForMASC()) {
// pop up are you sure dialog
Mech m = (Mech) ce();
ConfirmDialog nag = new ConfirmDialog(clientgui.frame, Messages.getString("MovementDisplay.areYouSure"), //$NON-NLS-1$
Messages.getString("MovementDisplay.ConfirmMoveRoll", new Object[] { new Integer(m.getMASCTarget()) }), //$NON-NLS-1$
true);
nag.setVisible(true);
if (nag.getAnswer()) {
// do they want to be bothered again?
if (!nag.getShowAgain()) {
GUIPreferences.getInstance().setNagForMASC(false);
}
} else {
return;
}
}
String check = SharedUtility.doPSRCheck(md, client);
if ((check.length() > 0) && GUIPreferences.getInstance().getNagForPSR() && !dontCheckPSR) {
ConfirmDialog nag = new ConfirmDialog(clientgui.frame, Messages.getString("MovementDisplay.areYouSure"), //$NON-NLS-1$
Messages.getString("MovementDisplay.ConfirmPilotingRoll") + //$NON-NLS-1$
check, true);
nag.setVisible(true);
if (nag.getAnswer()) {
// do they want to be bothered again?
if (!nag.getShowAgain()) {
GUIPreferences.getInstance().setNagForPSR(false);
}
} else {
return;
}
}
disableButtons();
clientgui.bv.clearMovementData();
if (ce().hasUMU() || (ce() instanceof LandAirMech)) {
client.sendUpdateEntity(ce());
}
client.moveEntity(cen, md);
}
/**
* Returns the current entity.
*/
private synchronized Entity ce() {
return client.game.getEntity(cen);
}
/**
* Returns new MovePath for the currently selected movement type
*/
private void currentMove(Coords dest) {
if (shiftheld || (gear == GEAR_TURN)) {
cmd.rotatePathfinder(cmd.getFinalCoords().direction(dest), false);
} else if ((gear == GEAR_LAND) || (gear == GEAR_JUMP)) {
cmd.findPathTo(dest, MovePath.STEP_FORWARDS);
} else if (gear == GEAR_BACKUP) {
cmd.findPathTo(dest, MovePath.STEP_BACKWARDS);
} else if (gear == GEAR_CHARGE) {
cmd.findPathTo(dest, MovePath.STEP_CHARGE);
} else if (gear == GEAR_DFA) {
cmd.findPathTo(dest, MovePath.STEP_DFA);
} else if (gear == GEAR_SWIM) {
cmd.findPathTo(dest, MovePath.STEP_SWIM);
} else if (gear == GEAR_RAM) {
cmd.findPathTo(dest, MovePath.STEP_FORWARDS);
} else if (gear == GEAR_IMMEL) {
cmd.addStep(MovePath.STEP_UP, true, true);
cmd.addStep(MovePath.STEP_UP, true, true);
cmd.addStep(MovePath.STEP_DEC, true, true);
cmd.addStep(MovePath.STEP_DEC, true, true);
cmd.rotatePathfinder(cmd.getFinalCoords().direction(dest), true);
gear = GEAR_LAND;
} else if (gear == GEAR_SPLIT_S) {
cmd.addStep(MovePath.STEP_DOWN, true, true);
cmd.addStep(MovePath.STEP_DOWN, true, true);
cmd.addStep(MovePath.STEP_ACC, true, true);
cmd.rotatePathfinder(cmd.getFinalCoords().direction(dest), true);
gear = GEAR_LAND;
}
}
//
// BoardListener
//
@Override
public synchronized void hexMoused(BoardViewEvent b) {
final Entity ce = ce();
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
// don't make a movement path for aeros if advanced movement is on
boolean nopath = (ce instanceof Aero) && client.game.useVectorMove();
// ignore buttons other than 1
if (!client.isMyTurn() || ((b.getModifiers() & InputEvent.BUTTON1_MASK) == 0)) {
return;
}
// control pressed means a line of sight check.
// added ALT_MASK by kenn
if (((b.getModifiers() & InputEvent.CTRL_MASK) != 0) || ((b.getModifiers() & InputEvent.ALT_MASK) != 0)) {
return;
}
// check for shifty goodness
if (shiftheld != ((b.getModifiers() & InputEvent.SHIFT_MASK) != 0)) {
shiftheld = (b.getModifiers() & InputEvent.SHIFT_MASK) != 0;
}
if ((b.getType() == BoardViewEvent.BOARD_HEX_DRAGGED) && !nopath) {
if (!b.getCoords().equals(clientgui.getBoardView().getLastCursor()) || shiftheld || (gear == MovementDisplay.GEAR_TURN)) {
clientgui.getBoardView().cursor(b.getCoords());
// either turn or move
if (ce != null) {
currentMove(b.getCoords());
clientgui.bv.drawMovementData(ce, cmd);
}
}
} else if (b.getType() == BoardViewEvent.BOARD_HEX_CLICKED) {
Coords moveto = b.getCoords();
clientgui.bv.drawMovementData(ce, cmd);
clientgui.getBoardView().select(b.getCoords());
if (shiftheld || (gear == MovementDisplay.GEAR_TURN)) {
butDone.setLabel(Messages.getString("MovementDisplay.Move")); //$NON-NLS-1$
// Set the button's label to "Done"
// if the entire move is impossible.
MovePath possible = cmd.clone();
possible.clipToPossible();
if (possible.length() == 0) {
butDone.setLabel(Messages.getString("MovementDisplay.Done")); //$NON-NLS-1$
}
return;
}
if (gear == MovementDisplay.GEAR_RAM) {
// check if target is valid
final Targetable target = chooseTarget(b.getCoords());
if ((target == null) || target.equals(ce) || !(target instanceof Aero)) {
clientgui.doAlertDialog(Messages.getString("MovementDisplay.CantRam"), Messages.getString("MovementDisplay.NoTarget")); //$NON-NLS-1$ //$NON-NLS-2$
clearAllMoves();
return;
}
// check if it's a valid ram
// First I need to add moves to the path if advanced
if ((ce instanceof Aero) && client.game.useVectorMove()) {
cmd.clipToPossible();
cmd = addSteps(cmd, ce);
}
cmd.addStep(MovePath.STEP_RAM);
ToHitData toHit = new RamAttackAction(cen, target.getTargetType(), target.getTargetId(), target.getPosition()).toHit(client.game, cmd);
if (toHit.getValue() != TargetRoll.IMPOSSIBLE) {
// Determine how much damage the charger will take.
Aero ta = (Aero) target;
Aero ae = (Aero) ce;
int toAttacker = RamAttackAction.getDamageTakenBy(ae, ta, cmd.getSecondFinalPosition(ae.getPosition()), cmd.getHexesMoved(), ta.getCurrentVelocity());
int toDefender = RamAttackAction.getDamageFor(ae, ta, cmd.getSecondFinalPosition(ae.getPosition()), cmd.getHexesMoved(), ta.getCurrentVelocity());
// Ask the player if they want to charge.
if (clientgui.doYesNoDialog(Messages.getString("MovementDisplay.RamDialog.title", new Object[] { target.getDisplayName() }), //$NON-NLS-1$
Messages.getString("MovementDisplay.RamDialog.message", new Object[] { //$NON-NLS-1$
toHit.getValueAsString(), new Double(Compute.oddsAbove(toHit.getValue())), toHit.getDesc(), new Integer(toDefender), toHit.getTableDesc(), new Integer(toAttacker) }))) {
// if they answer yes, charge the target.
cmd.getLastStep().setTarget(target);
moveTo(cmd);
} else {
// else clear movement
clearAllMoves();
}
return;
}
// if not valid, tell why
clientgui.doAlertDialog(Messages.getString("MovementDisplay.CantRam"), //$NON-NLS-1$
toHit.getDesc());
clearAllMoves();
return;
} else if (gear == MovementDisplay.GEAR_CHARGE) {
// check if target is valid
final Targetable target = chooseTarget(b.getCoords());
if ((target == null) || target.equals(ce)) {
clientgui.doAlertDialog(Messages.getString("MovementDisplay.CantCharge"), Messages.getString("MovementDisplay.NoTarget")); //$NON-NLS-1$ //$NON-NLS-2$
clearAllMoves();
return;
}
ToHitData toHit = new ChargeAttackAction(cen, target.getTargetType(), target.getTargetId(), target.getPosition()).toHit(client.game, cmd);
if (toHit.getValue() != TargetRoll.IMPOSSIBLE) {
// Determine how much damage the charger will take.
int toAttacker = 0;
if (target.getTargetType() == Targetable.TYPE_ENTITY) {
Entity te = (Entity) target;
toAttacker = ChargeAttackAction.getDamageTakenBy(ce, te, client.game.getOptions().booleanOption("tacops_charge_damage"), cmd.getHexesMoved()); //$NON-NLS-1$
} else if ((target.getTargetType() == Targetable.TYPE_FUEL_TANK) || (target.getTargetType() == Targetable.TYPE_BUILDING)) {
Building bldg = client.game.getBoard().getBuildingAt(moveto);
toAttacker = ChargeAttackAction.getDamageTakenBy(ce, bldg, moveto);
}
// Ask the player if they want to charge.
if (clientgui.doYesNoDialog(Messages.getString("MovementDisplay.ChargeDialog.title", new Object[] { target.getDisplayName() }), //$NON-NLS-1$
Messages.getString("MovementDisplay.ChargeDialog.message", new Object[] { //$NON-NLS-1$
toHit.getValueAsString(), new Double(Compute.oddsAbove(toHit.getValue())), toHit.getDesc(), new Integer(ChargeAttackAction.getDamageFor(ce, client.game.getOptions().booleanOption("tacops_charge_damage"), cmd.getHexesMoved())), toHit.getTableDesc(), new Integer(toAttacker) }))) {
// if they answer yes, charge the target.
cmd.getLastStep().setTarget(target);
moveTo(cmd);
} else {
// else clear movement
clearAllMoves();
}
return;
}
// if not valid, tell why
clientgui.doAlertDialog(Messages.getString("MovementDisplay.CantCharge"), //$NON-NLS-1$
toHit.getDesc());
clearAllMoves();
return;
} else if (gear == MovementDisplay.GEAR_DFA) {
// check if target is valid
final Targetable target = chooseTarget(b.getCoords());
if ((target == null) || target.equals(ce)) {
clientgui.doAlertDialog(Messages.getString("MovementDisplay.CantDFA"), Messages.getString("MovementDisplay.NoTarget")); //$NON-NLS-1$ //$NON-NLS-2$
clearAllMoves();
return;
}
// check if it's a valid DFA
ToHitData toHit = DfaAttackAction.toHit(client.game, cen, target, cmd);
if (toHit.getValue() != TargetRoll.IMPOSSIBLE) {
// if yes, ask them if they want to DFA
if (clientgui.doYesNoDialog(Messages.getString("MovementDisplay.DFADialog.title", new Object[] { target.getDisplayName() }), //$NON-NLS-1$
Messages.getString("MovementDisplay.DFADialog.message", new Object[] { //$NON-NLS-1$
toHit.getValueAsString(), new Double(Compute.oddsAbove(toHit.getValue())), toHit.getDesc(), new Integer(DfaAttackAction.getDamageFor(ce, (target instanceof Infantry) && !(target instanceof BattleArmor))), toHit.getTableDesc(), new Integer(DfaAttackAction.getDamageTakenBy(ce)) }))) {
// if they answer yes, DFA the target
cmd.getLastStep().setTarget(target);
moveTo(cmd);
} else {
// else clear movement
clearAllMoves();
}
return;
}
// if not valid, tell why
clientgui.doAlertDialog(Messages.getString("MovementDisplay.CantDFA"), //$NON-NLS-1$
toHit.getDesc());
clearAllMoves();
return;
}
butDone.setLabel(Messages.getString("MovementDisplay.Move")); //$NON-NLS-1$
updateProneButtons();
updateRACButton();
updateSearchlightButton();
updateLoadButtons();
updateElevationButtons();
updateFleeButton();
updateLaunchButton();
updateRecklessButton();
updateHoverButton();
updateManeuverButton();
updateSpeedButtons();
updateThrustButton();
updateRollButton();
checkFuel();
checkOOC();
checkAtmosphere();
}
}
private synchronized void updateProneButtons() {
final Entity ce = ce();
if (ce != null) {
boolean isMech = ce instanceof Mech;
if (cmd.getFinalProne()) {
setGetUpEnabled(!ce.isImmobile() && !ce.isStuck());
setGoProneEnabled(false);
setHullDownEnabled(true);
} else if (cmd.getFinalHullDown()) {
if (isMech) {
setGetUpEnabled(!ce.isImmobile() && !ce.isStuck() && !((Mech)ce).cannotStandUpFromHullDown());
} else {
setGetUpEnabled(!ce.isImmobile() && !ce.isStuck());
}
setGoProneEnabled(!ce.isImmobile() && isMech && !ce.isStuck());
setHullDownEnabled(false);
} else {
setGetUpEnabled(false);
setGoProneEnabled(!ce.isImmobile() && isMech && !ce.isStuck() && !(butUp.isEnabled()));
setHullDownEnabled(ce.canGoHullDown());
}
} else {
setGetUpEnabled(false);
setGoProneEnabled(false);
setHullDownEnabled(false);
}
}
private void updateRACButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
setUnjamEnabled(ce.canUnjamRAC() && ((gear == MovementDisplay.GEAR_LAND) || (gear == MovementDisplay.GEAR_TURN) || (gear == MovementDisplay.GEAR_BACKUP)) && (cmd.getMpUsed() <= ce.getWalkMP()));
}
private void updateSearchlightButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
setSearchlightEnabled(ce.hasSpotlight() && !cmd.contains(MovePath.STEP_SEARCHLIGHT), ce().isUsingSpotlight());
}
private synchronized void updateElevationButtons() {
final Entity ce = ce();
if (null == ce) {
return;
}
if ((ce instanceof Aero) && ((Aero) ce).isOutControlTotal()) {
setRaiseEnabled(false);
setLowerEnabled(false);
return;
}
setRaiseEnabled(ce.canGoUp(cmd.getFinalElevation(), cmd.getFinalCoords()));
setLowerEnabled(ce.canGoDown(cmd.getFinalElevation(), cmd.getFinalCoords()));
}
private void updateRollButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
setRollEnabled(true);
if (client.game.getBoard().inAtmosphere()) {
setRollEnabled(false);
}
if (cmd.contains(MovePath.STEP_ROLL)) {
setRollEnabled(false);
}
return;
}
private void updateHoverButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
Aero a = (Aero) ce;
if (!(a.isSpheroid() || client.game.getPlanetaryConditions().isVacuum())) {
return;
}
if (!client.game.getBoard().inAtmosphere()) {
return;
}
if (!cmd.contains(MovePath.STEP_HOVER)) {
setHoverEnabled(true);
} else {
setHoverEnabled(false);
}
return;
}
private void updateThrustButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
Aero a = (Aero) ce;
// only allow thrust if there is thrust left to spend
int mpUsed = 0;
MoveStep last = cmd.getLastStep();
if (null != last) {
mpUsed = last.getMpUsed();
}
if (mpUsed >= a.getRunMP()) {
setThrustEnabled(false);
} else {
setThrustEnabled(true);
}
return;
}
private synchronized void updateSpeedButtons() {
final Entity ce = ce();
if (null == ce) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
Aero a = (Aero) ce;
// only allow acceleration and deceleration if the cmd is empty or the
// last step was
// acc/dec
setAccEnabled(false);
setDecEnabled(false);
MoveStep last = cmd.getLastStep();
// figure out implied velocity so you can't decelerate below zero
int vel = a.getCurrentVelocity();
int veln = a.getNextVelocity();
if (null != last) {
vel = last.getVelocity();
veln = last.getVelocityN();
}
if (null == last) {
setAccEnabled(true);
if (vel > 0) {
setDecEnabled(true);
}
} else if (last.getType() == MovePath.STEP_ACC) {
setAccEnabled(true);
} else if ((last.getType() == MovePath.STEP_DEC) && (vel > 0)) {
setDecEnabled(true);
}
// if the aero has failed a maneuver this turn, then don't allow
if (a.didFailManeuver()) {
setAccEnabled(false);
setDecEnabled(false);
}
// if accelerated/decelerate at the end of last turn then disable
if (a.didAccLast()) {
setAccEnabled(false);
setDecEnabled(false);
}
// allow acc/dec next if acceleration/deceleration hasn't been used
setAccNEnabled(false);
setDecNEnabled(false);
if (!cmd.contains(MovePath.STEP_ACC) && !cmd.contains(MovePath.STEP_DEC) && !cmd.contains(MovePath.STEP_DECN)) {
setAccNEnabled(true);
}
if (!cmd.contains(MovePath.STEP_ACC) && !cmd.contains(MovePath.STEP_DEC) && !cmd.contains(MovePath.STEP_ACCN) && (veln > 0)) {
setDecNEnabled(true);
}
// acc/dec next needs to be disabled if acc/dec used before a failed
// maneuver
if (a.didFailManeuver() && a.didAccDecNow()) {
setDecNEnabled(false);
setAccNEnabled(false);
}
//if in atmosphere, limit acceleration to 2x safe thrust
if(!client.game.getBoard().inSpace() && (vel == (2 * a.getWalkMP()))) {
setAccEnabled(false);
}
//velocity next will get halved before next turn so allow up to 4 times
if(!client.game.getBoard().inSpace() && (veln == (4 * a.getWalkMP()))) {
setAccNEnabled(false);
}
// if this is a tele-operated missile then it can't decelerate no matter
// what
if (a instanceof TeleMissile) {
setDecEnabled(false);
setDecNEnabled(false);
}
return;
}
private void updateDumpButton() {
/*
if (ce() instanceof Aero) {
Aero a = (Aero) ce();
setDumpEnabled(a.hasBombs() && cmd.length() == 0);
} else {
setDumpEnabled(false);
}
*/
}
private void updateFleeButton() {
final Entity ce = ce();
// Aeros should be able to flee if they reach a border hex with velocity
// remaining
// and facing the right direction
if (ce instanceof Aero) {
MoveStep step = cmd.getLastStep();
Coords position = ce.getPosition();
int facing = ce.getFacing();
Aero a = (Aero) ce;
int velocityLeft = a.getCurrentVelocity();
if (step != null) {
position = step.getPosition();
facing = step.getFacing();
velocityLeft = step.getVelocityLeft();
}
boolean evenx = (position.x % 2) == 0;
if ((velocityLeft > 0) && (((position.x == 0) && ((facing == 5) || (facing == 4))) || ((position.x == client.game.getBoard().getWidth() - 1) && ((facing == 1) || (facing == 2))) || ((position.y == 0) && ((facing == 1) || (facing == 5) || (facing == 0)) && evenx) || ((position.y == 0) && (facing == 0)) || ((position.y == client.game.getBoard().getHeight() - 1) && ((facing == 2) || (facing == 3) || (facing == 4)) && !evenx) || ((position.y == client.game.getBoard().getHeight() - 1) && (facing == 3)))) {
setFleeEnabled(true);
} else {
setFleeEnabled(false);
}
}
}
private void updateLaunchButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
setLaunchEnabled((ce.getLaunchableFighters().size() > 0) || (ce.getLaunchableSmallCraft().size() > 0));
}
private void updateRecklessButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
if(ce instanceof Protomech) {
setRecklessEnabled(false);
} else {
setRecklessEnabled((null == cmd) || (cmd.length() == 0));
}
}
private void updateManeuverButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
if(client.game.getBoard().inSpace() || client.game.getBoard().onGround()) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
Aero a = (Aero) ce;
if (a.isSpheroid() || client.game.getPlanetaryConditions().isVacuum()) {
return;
}
if (!a.didFailManeuver() && ((null == cmd) || !cmd.contains(MovePath.STEP_MANEUVER))) {
setManeuverEnabled(true);
}
return;
}
private synchronized void updateLoadButtons() {
final Entity ce = ce();
if (null == ce) {
return;
}
boolean legalGear = ((gear == MovementDisplay.GEAR_LAND) || (gear == MovementDisplay.GEAR_TURN) || (gear == MovementDisplay.GEAR_BACKUP));
int unloadEl = cmd.getFinalElevation();
IHex hex = ce.getGame().getBoard().getHex(cmd.getFinalCoords());
boolean canUnloadHere = false;
for (Entity en : loadedUnits) {
if (en.isElevationValid(unloadEl, hex) || (en.getJumpMP() > 0)) {
canUnloadHere = true;
break;
}
}
// Disable the "Unload" button if we're in the wrong
// gear or if the entity is not transporting units.
if (!legalGear || (loadedUnits.size() == 0) || (cen == Entity.NONE) || (!canUnloadHere)) {
setUnloadEnabled(false);
} else {
setUnloadEnabled(true);
}
// If the current entity has moved, disable "Load" button.
if ((cmd.length() > 0) || (cen == Entity.NONE)) {
setLoadEnabled(false);
} else {
// Check the other entities in the current hex for friendly units.
Entity other = null;
Enumeration<Entity> entities = client.game.getEntities(ce.getPosition());
boolean isGood = false;
while (entities.hasMoreElements()) {
// Is the other unit friendly and not the current entity?
other = entities.nextElement();
if (!ce.getOwner().isEnemyOf(other.getOwner()) && !ce.equals(other)) {
// Yup. If the current entity has at least 1 MP, if it can
// transport the other unit, and if the other hasn't moved
// then enable the "Load" button.
if ((ce.getWalkMP() > 0) && ce.canLoad(other) && other.isLoadableThisTurn()) {
setLoadEnabled(true);
isGood = true;
}
// We can stop looking.
break;
}
// Nope. Discard it.
other = null;
} // Check the next entity in this position.
if (!isGood) {
setLoadEnabled(false);
}
} // End ce-hasn't-moved
} // private void updateLoadButtons
/**
* Get the unit that the player wants to unload. This method will remove the
* unit from our local copy of loaded units.
*
* @return The <code>Entity</code> that the player wants to unload. This
* value will not be <code>null</code>.
*/
private Entity getUnloadedUnit() {
Entity ce = ce();
Entity choice = null;
// Handle error condition.
if (loadedUnits.size() == 0) {
System.err.println("MovementDisplay#getUnloadedUnit() called without loaded units."); //$NON-NLS-1$
}
// If we have multiple choices, display a selection dialog.
else if (loadedUnits.size() > 1) {
String[] names = new String[loadedUnits.size()];
String question = Messages.getString("MovementDisplay.UnloadUnitDialog.message", new Object[] { //$NON-NLS-1$
ce.getShortName(), ce.getUnusedString() });
for (int loop = 0; loop < names.length; loop++) {
names[loop] = loadedUnits.elementAt(loop).getShortName();
}
SingleChoiceDialog choiceDialog = new SingleChoiceDialog(clientgui.frame, Messages.getString("MovementDisplay.UnloadUnitDialog.title"), //$NON-NLS-1$
question, names);
choiceDialog.setVisible(true);
if (choiceDialog.getAnswer() == true) {
choice = loadedUnits.elementAt(choiceDialog.getChoice());
}
} // End have-choices
// Only one choice.
else {
choice = loadedUnits.elementAt(0);
loadedUnits.removeElementAt(0);
}
// Return the chosen unit.
return choice;
}
/**
* FIGHTER RECOVERY fighter recovery will be handled differently than
* loading other units. Namely, it will be an action of the fighter not the
* carrier. So the fighter just flies right up to a carrier whose movement
* is ended and hops on. need a new function
*/
private synchronized void updateRecoveryButton() {
final Entity ce = ce();
if (null == ce) {
return;
}
// I also want to handle fighter recovery here. If using advanced
// movement
// it is not a function of where carrier is but where the carrier will
// be at the end
// of its move
if (ce instanceof Aero) {
Coords loadeePos = cmd.getFinalCoords();
if (client.game.useVectorMove()) {
// not where you are, but where you will be
loadeePos = Compute.getFinalPosition(ce.getPosition(), cmd.getFinalVectors());
}
Entity other = null;
Enumeration<Entity> entities = client.game.getEntities(loadeePos);
boolean isGood = false;
while (entities.hasMoreElements()) {
// Is the other unit friendly and not the current entity?
other = entities.nextElement();
if (!ce.getOwner().isEnemyOf(other.getOwner()) && !ce.equals(other)) {
// must be done with its movement
// it also must be same heading and velocity
if ((other instanceof Aero) && other.isDone() && other.canLoad(ce) && (cmd.getFinalFacing() == other.getFacing()) && !other.isCapitalFighter()) {
// now lets check velocity
// depends on movement rules
Aero oa = (Aero) other;
if (client.game.useVectorMove()) {
if (Compute.sameVectors(cmd.getFinalVectors(), oa.getVectors())) {
setRecoverEnabled(true);
isGood = true;
}
} else if (cmd.getFinalVelocity() == oa.getCurrentVelocity()) {
setRecoverEnabled(true);
isGood = true;
}
}
}
// Nope. Discard it.
other = null;
} // Check the next entity in this position.
if (!isGood) {
setRecoverEnabled(false);
}
}
}
/**
* Joining a squadron - Similar to fighter recovery. You can fly up and join a squadron or another solo fighter
*/
private synchronized void updateJoinButton() {
if(!client.game.getOptions().booleanOption("stratops_capital_fighter")) {
return;
}
final Entity ce = ce();
if (null == ce) {
return;
}
if(!ce.isCapitalFighter()) {
return;
}
Coords loadeePos = cmd.getFinalCoords();
if (client.game.useVectorMove()) {
// not where you are, but where you will be
loadeePos = Compute.getFinalPosition(ce.getPosition(), cmd.getFinalVectors());
}
Entity other = null;
Enumeration<Entity> entities = client.game.getEntities(loadeePos);
boolean isGood = false;
while (entities.hasMoreElements()) {
// Is the other unit friendly and not the current entity?
other = entities.nextElement();
if (!ce.getOwner().isEnemyOf(other.getOwner()) && !ce.equals(other)) {
// must be done with its movement
// it also must be same heading and velocity
if (other.isCapitalFighter() && other.isDone() && other.canLoad(ce) && (cmd.getFinalFacing() == other.getFacing())) {
// now lets check velocity
// depends on movement rules
Aero oa = (Aero) other;
if (client.game.useVectorMove()) {
// can you do equality with vectors?
if (Compute.sameVectors(cmd.getFinalVectors(), oa.getVectors())) {
setJoinEnabled(true);
isGood = true;
}
} else if (cmd.getFinalVelocity() == oa.getCurrentVelocity()) {
setJoinEnabled(true);
isGood = true;
}
}
}
// Nope. Discard it.
other = null;
} // Check the next entity in this position.
if (!isGood) {
setJoinEnabled(false);
}
}
/**
* Get the unit that the player wants to unload. This method will remove the
* unit from our local copy of loaded units.
*
* @return The <code>Entity</code> that the player wants to unload. This
* value will not be <code>null</code>.
*/
private TreeMap<Integer, Vector<Integer>> getLaunchedUnits() {
Entity ce = ce();
TreeMap<Integer, Vector<Integer>> choices = new TreeMap<Integer, Vector<Integer>>();
Vector<Entity> launchableFighters = ce.getLaunchableFighters();
Vector<Entity> launchableSmallCraft = ce.getLaunchableSmallCraft();
// Handle error condition.
if ((launchableFighters.size() <= 0) && (launchableSmallCraft.size() <= 0)) {
System.err.println("MovementDisplay#getUnloadedUnit() called without loaded units."); //$NON-NLS-1$
} else {
// cycle through the fighter bays and then the small craft bays
int bayNum = 1;
Bay currentBay;
Vector<Entity> currentFighters = new Vector<Entity>();
int doors = 0;
Vector<Bay> FighterBays = ce.getFighterBays();
for (int i = 0; i < FighterBays.size(); i++) {
currentBay = FighterBays.elementAt(i);
Vector<Integer> bayChoices = new Vector<Integer>();
currentFighters = currentBay.getLaunchableUnits();
/*
* We will assume that if more fighters are launched than is safe, that these excess fighters
* will be distributed equally among available doors
*/
doors = currentBay.getDoors();
if (currentFighters.size() > 0) {
String[] names = new String[currentFighters.size()];
String question = Messages.getString("MovementDisplay.LaunchFighterDialog.message", new Object[] { //$NON-NLS-1$
ce.getShortName(), doors*2, bayNum});
for(int loop = 0; loop < names.length; loop++) {
names[loop] = currentFighters.elementAt(loop).getShortName();
}
ChoiceDialog choiceDialog = new ChoiceDialog(clientgui.frame, Messages.getString("MovementDisplay.LaunchFighterDialog.title", new Object[] { //$NON-NLS-1$
currentBay.getType(), bayNum}),
question, names);
choiceDialog.setVisible(true);
if (choiceDialog.getAnswer() == true) {
// load up the choices
int[] unitsLaunched = choiceDialog.getChoices();
for (int element : unitsLaunched) {
bayChoices.add(currentFighters.elementAt(element).getId());
}
choices.put(i, bayChoices);
// now remove them (must be a better way?)
for (int l = unitsLaunched.length; l > 0; l--) {
currentFighters.remove(unitsLaunched[l - 1]);
}
}
}
bayNum++;
}
}// End have-choices
// Return the chosen unit.
return choices;
}
/**
* @return the unit id that the player wants to be recovered by
*/
private int getRecoveryUnit() {
Entity ce = ce();
Vector<Integer> choices = new Vector<Integer>();
// collect all possible choices
Coords loadeePos = cmd.getFinalCoords();
if (client.game.useVectorMove()) {
// not where you are, but where you will be
loadeePos = Compute.getFinalPosition(ce.getPosition(), cmd.getFinalVectors());
}
Entity other = null;
Enumeration<Entity> entities = client.game.getEntities(loadeePos);
while (entities.hasMoreElements()) {
// Is the other unit friendly and not the current entity?
other = entities.nextElement();
if (!ce.getOwner().isEnemyOf(other.getOwner()) && !ce.equals(other)) {
// must be done with its movement
// it also must be same heading and velocity
if ((other instanceof Aero) && !((Aero) other).isOutControlTotal() && other.isDone() && other.canLoad(ce) && ce.isLoadableThisTurn() && (cmd.getFinalFacing() == other.getFacing())) {
// now lets check velocity
// depends on movement rules
Aero oa = (Aero) other;
if (client.game.useVectorMove()) {
if (Compute.sameVectors(cmd.getFinalVectors(), oa.getVectors())) {
choices.add(other.getId());
}
} else if (cmd.getFinalVelocity() == oa.getCurrentVelocity()) {
choices.add(other.getId());
}
}
}
// Nope. Discard it.
other = null;
} // Check the next entity in this position.
if (choices.size() < 1) {
return -1;
}
if (choices.size() == 1) {
if (client.game.getEntity(choices.elementAt(0)).mpUsed > 0) {
if (clientgui.doYesNoDialog(Messages.getString("MovementDisplay.RecoverSureDialog.title"), //$NON-NLS-1$
Messages.getString("MovementDisplay.RecoverSureDialog.message") //$NON-NLS-1$
)) {
return choices.elementAt(0);
}
} else {
return choices.elementAt(0);
}
return -1;
}
String[] names = new String[choices.size()];
for (int loop = 0; loop < names.length; loop++) {
names[loop] = client.game.getEntity(choices.elementAt(loop)).getShortName();
}
String question = Messages.getString("MovementDisplay.RecoverFighterDialog.message");
SingleChoiceDialog choiceDialog = new SingleChoiceDialog(clientgui.frame, Messages.getString("MovementDisplay.RecoverFighterDialog.title"), question, names);
choiceDialog.setVisible(true);
if (choiceDialog.getAnswer()) {
// if this unit is thrusting, make sure they are aware
if (client.game.getEntity(choices.elementAt(choiceDialog.getChoice())).mpUsed > 0) {
if (clientgui.doYesNoDialog(Messages.getString("MovementDisplay.RecoverSureDialog.title"), //$NON-NLS-1$
Messages.getString("MovementDisplay.RecoverSureDialog.message") //$NON-NLS-1$
)) {
return choices.elementAt(choiceDialog.getChoice());
}
} else {
return choices.elementAt(choiceDialog.getChoice());
}
}
return -1;
}
/**
* @return the unit id that the player wants to join
*/
private int getUnitJoined() {
Entity ce = ce();
Vector<Integer> choices = new Vector<Integer>();
// collect all possible choices
Coords loadeePos = cmd.getFinalCoords();
if (client.game.useVectorMove()) {
// not where you are, but where you will be
loadeePos = Compute.getFinalPosition(ce.getPosition(), cmd.getFinalVectors());
}
Entity other = null;
Enumeration<Entity> entities = client.game.getEntities(loadeePos);
while (entities.hasMoreElements()) {
// Is the other unit friendly and not the current entity?
other = entities.nextElement();
if (!ce.getOwner().isEnemyOf(other.getOwner()) && !ce.equals(other)) {
// must be done with its movement
// it also must be same heading and velocity
if ((other instanceof Aero) && !((Aero) other).isOutControlTotal() && other.isDone() && other.canLoad(ce) && ce.isLoadableThisTurn() && (cmd.getFinalFacing() == other.getFacing())) {
// now lets check velocity
// depends on movement rules
Aero oa = (Aero) other;
if (client.game.useVectorMove()) {
if (Compute.sameVectors(cmd.getFinalVectors(), oa.getVectors())) {
choices.add(other.getId());
}
} else if (cmd.getFinalVelocity() == oa.getCurrentVelocity()) {
choices.add(other.getId());
}
}
}
// Nope. Discard it.
other = null;
} // Check the next entity in this position.
if (choices.size() < 1) {
return -1;
}
if (choices.size() == 1) {
return choices.elementAt(0);
}
String[] names = new String[choices.size()];
for (int loop = 0; loop < names.length; loop++) {
names[loop] = client.game.getEntity(choices.elementAt(loop)).getShortName();
}
String question = Messages.getString("MovementDisplay.JoinSquadronDialog.message");
SingleChoiceDialog choiceDialog = new SingleChoiceDialog(clientgui.frame, Messages.getString("MovementDisplay.JoinSquadronDialog.title"), question, names);
choiceDialog.setVisible(true);
if (choiceDialog.getAnswer()) {
return choices.elementAt(choiceDialog.getChoice());
}
return -1;
}
// check for out of control and adjust buttons
private void checkOOC() {
final Entity ce = ce();
if (null == ce) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
Aero a = (Aero) ce;
if (a.isOutControlTotal()) {
disableButtons();
butDone.setEnabled(true);
butNext.setEnabled(true);
butLaunch.setEnabled(true);
}
return;
}
// check for fuel and adjust buttons
private void checkFuel() {
final Entity ce = ce();
if (null == ce) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
Aero a = (Aero) ce;
if (a.getFuel() < 1) {
disableButtons();
butDone.setEnabled(true);
butNext.setEnabled(true);
butLaunch.setEnabled(true);
updateRACButton();
updateRecoveryButton();
updateJoinButton();
updateDumpButton();
}
return;
}
// check for atmosphere and adjust buttons
private void checkAtmosphere() {
final Entity ce = ce();
if (null == ce) {
return;
}
if (!(ce instanceof Aero)) {
return;
}
Aero a = (Aero) ce;
if (client.game.getBoard().inAtmosphere()) {
if (a.isSpheroid() || client.game.getPlanetaryConditions().isVacuum()) {
butAcc.setEnabled(false);
butDec.setEnabled(false);
butAccN.setEnabled(false);
butDecN.setEnabled(false);
}
}
return;
}
/**
* Have the player select a target from the entities at the given coords.
*
* @param pos -
* the <code>Coords</code> containing targets.
*/
private Targetable chooseTarget(Coords pos) {
final Entity ce = ce();
// Assume that we have *no* choice.
Targetable choice = null;
// Get the available choices.
Enumeration<Entity> choices = client.game.getEntities(pos);
// Convert the choices into a List of targets.
Vector<Targetable> targets = new Vector<Targetable>();
while (choices.hasMoreElements()) {
choice = choices.nextElement();
if (!ce.equals(choice)) {
targets.addElement(choice);
}
}
// Is there a building in the hex?
Building bldg = client.game.getBoard().getBuildingAt(pos);
if (bldg != null) {
targets.addElement(new BuildingTarget(pos, client.game.getBoard(), false));
}
// Do we have a single choice?
if (targets.size() == 1) {
// Return that choice.
choice = targets.elementAt(0);
}
// If we have multiple choices, display a selection dialog.
else if (targets.size() > 1) {
String[] names = new String[targets.size()];
String question = Messages.getString("MovementDisplay.ChooseTargetDialog.message", new Object[] {//$NON-NLS-1$
pos.getBoardNum() });
for (int loop = 0; loop < names.length; loop++) {
names[loop] = targets.elementAt(loop).getDisplayName();
}
SingleChoiceDialog choiceDialog = new SingleChoiceDialog(clientgui.frame, Messages.getString("MovementDisplay.ChooseTargetDialog.title"), //$NON-NLS-1$
question.toString(), names);
choiceDialog.setVisible(true);
if (choiceDialog.getAnswer() == true) {
choice = targets.elementAt(choiceDialog.getChoice());
}
} // End have-choices
// Return the chosen unit.
return choice;
} // End private Targetable chooseTarget( Coords )
private int chooseMineToLay() {
MineLayingDialog mld = new MineLayingDialog(clientgui.frame, ce());
mld.setVisible(true);
if (mld.getAnswer() == true) {
return mld.getMine();
}
return -1;
}
private void dumpBombs() {
if (!(ce() instanceof Aero)) {
return;
}
Aero a = (Aero) ce();
int overallMoveType = IEntityMovementType.MOVE_NONE;
if(null != cmd) {
overallMoveType = cmd.getLastStepMovementType();
}
// bring up dialog to dump bombs, then make a control roll and report
// success or failure
// should update mp available
BombPayloadDialog dumpBombsDialog = new BombPayloadDialog(clientgui.frame, Messages.getString("MovementDisplay.BombDumpDialog.title"), //$NON-NLS-1$
a.getBombChoices(), false, true);
dumpBombsDialog.setVisible(true);
if (dumpBombsDialog.getAnswer()) {
/*
int[] bombsDumped = dumpBombsDialog.getChoices();
// first make a control roll
PilotingRollData psr = ce().getBasePilotingRoll(overallMoveType);
int ctrlroll = Compute.d6(2);
Report r = new Report(9500);
r.subject = ce().getId();
r.add(ce().getDisplayName());
r.add(psr.getValue());
r.add(ctrlroll);
r.newlines = 0;
r.indent(1);
if (ctrlroll < psr.getValue()) {
r.choose(false);
// addReport(r);
String title = Messages.getString("MovementDisplay.DumpingBombs.title"); //$NON-NLS-1$
String body = Messages.getString("MovementDisplay.DumpFailure.message"); //$NON-NLS-1$
clientgui.doAlertDialog(title, body);
// failed the roll, so dump all bombs
bombsDumped = a.getBombChoices();
} else {
// avoided damage
r.choose(true);
String title = Messages.getString("MovementDisplay.DumpingBombs.title"); //$NON-NLS-1$
String body = Messages.getString("MovementDisplay.DumpSuccessful.message"); //$NON-NLS-1$
clientgui.doAlertDialog(title, body);
// addReport(r);
*
*/
//}
/*
// now unload the bombs
for (int j = 0; j < bombsDumped.length; j++) {
if (bombsDumped[j] > 0) {
a.removeBombs(bombsDumped[j], j);
// Report r = new Report(5115);
r.subject = ce().getId();
r.addDesc(ce());
r.add("" + bombsDumped[j] + " " + Aero.bombNames[j] + "(s)");
// addReport(r);
}
}
// update the bomb load immediately
a.updateBombLoad();
client.sendUpdateEntity(ce());
*/
// not sure how to update mech display, but everything else is
// working
}
}
/**
* based on maneuver type add the appropriate steps return true if we should
* redraw the movement data
*/
private boolean addManeuver(int type) {
cmd.addManeuver(type);
switch (type) {
case (ManeuverType.MAN_HAMMERHEAD):
cmd.addStep(MovePath.STEP_YAW, true, true);
return true;
case (ManeuverType.MAN_HALF_ROLL):
cmd.addStep(MovePath.STEP_ROLL, true, true);
return true;
case (ManeuverType.MAN_BARREL_ROLL):
cmd.addStep(MovePath.STEP_DEC, true, true);
return true;
case (ManeuverType.MAN_IMMELMAN):
gear = MovementDisplay.GEAR_IMMEL;
return false;
case (ManeuverType.MAN_SPLIT_S):
gear = MovementDisplay.GEAR_SPLIT_S;
return false;
case (ManeuverType.MAN_VIFF):
if (!(ce() instanceof Aero)) {
return false;
}
Aero a = (Aero) ce();
MoveStep last = cmd.getLastStep();
int vel = a.getCurrentVelocity();
if (null != last) {
vel = last.getVelocityLeft();
}
while (vel > 0) {
cmd.addStep(MovePath.STEP_DEC, true, true);
vel--;
}
cmd.addStep(MovePath.STEP_UP);
return true;
case (ManeuverType.MAN_SIDE_SLIP_LEFT):
cmd.addStep(MovePath.STEP_LATERAL_LEFT, true, true);
return true;
case (ManeuverType.MAN_SIDE_SLIP_RIGHT):
cmd.addStep(MovePath.STEP_LATERAL_RIGHT, true, true);
return true;
case (ManeuverType.MAN_LOOP):
cmd.addStep(MovePath.STEP_LOOP, true, true);
return true;
default:
return false;
}
}
//
// GameListener
//
@Override
public void gameTurnChange(GameTurnChangeEvent e) {
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
if (client.game.getPhase() != IGame.Phase.PHASE_MOVEMENT) {
// ignore
return;
}
// else, change turn
endMyTurn();
if (client.isMyTurn()) {
// Can the player unload entities stranded on immobile transports?
if (client.canUnloadStranded()) {
unloadStranded();
} else {
beginMyTurn();
}
} else {
if ((e.getPlayer() == null) && (client.game.getTurn() instanceof GameTurn.UnloadStrandedTurn)) {
setStatusBarText(Messages.getString("MovementDisplay.waitForAnother")); //$NON-NLS-1$
} else {
setStatusBarText(Messages.getString("MovementDisplay.its_others_turn", new Object[] { e.getPlayer().getName() })); //$NON-NLS-1$
}
}
}
@Override
public void gamePhaseChange(GamePhaseChangeEvent e) {
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
if (client.isMyTurn() && (client.game.getPhase() != IGame.Phase.PHASE_MOVEMENT)) {
endMyTurn();
}
if (client.game.getPhase() == IGame.Phase.PHASE_MOVEMENT) {
setStatusBarText(Messages.getString("MovementDisplay.waitingForMovementPhase")); //$NON-NLS-1$
}
}
//
// ActionListener
//
public synchronized void actionPerformed(ActionEvent ev) {
final Entity ce = ce();
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
if (statusBarActionPerformed(ev, client)) {
return;
}
if (!client.isMyTurn()) {
// odd...
return;
}
if (ev.getSource() == butDone) {
moveTo(cmd);
} else if (ev.getActionCommand().equals(MOVE_NEXT)) {
selectEntity(client.getNextEntityNum(cen));
} else if (ev.getActionCommand().equals(MOVE_CANCEL)) {
clearAllMoves();
} else if (ev.getSource() == butMore) {
buttonLayout++;
buttonLayout %= NUM_BUTTON_LAYOUTS;
setupButtonPanel();
} else if (ev.getActionCommand().equals(MOVE_UNJAM)) {
if ((gear == MovementDisplay.GEAR_JUMP)
|| (gear == MovementDisplay.GEAR_CHARGE)
|| (gear == MovementDisplay.GEAR_DFA)
|| (cmd.getMpUsed() > ce.getWalkMP())
|| (gear == MovementDisplay.GEAR_SWIM)
|| (gear == MovementDisplay.GEAR_RAM)) {
// in the wrong gear
setUnjamEnabled(false);
} else {
cmd.addStep(MovePath.STEP_UNJAM_RAC);
moveTo(cmd);
}
} else if (ev.getActionCommand().equals(MOVE_SEARCHLIGHT)) {
cmd.addStep(MovePath.STEP_SEARCHLIGHT);
} else if (ev.getActionCommand().equals(MOVE_WALK)) {
if ((gear == MovementDisplay.GEAR_JUMP) || (gear == MovementDisplay.GEAR_SWIM)) {
clearAllMoves();
}
gear = MovementDisplay.GEAR_LAND;
} else if (ev.getActionCommand().equals(MOVE_JUMP)) {
if ((ce instanceof LandAirMech) && ((LandAirMech) ce).isInMode(LandAirMech.MODE_AIRMECH)) {
if (cmd.isFlying()) {
cmd.addStep(MovePath.STEP_LAND);
gear = MovementDisplay.GEAR_JUMP;
} else {
cmd.addStep(MovePath.STEP_TAKEOFF);
gear = MovementDisplay.GEAR_JUMP;
}
} else {
if (gear != MovementDisplay.GEAR_JUMP) {
clearAllMoves();
}
if (!cmd.isJumping()) {
cmd.addStep(MovePath.STEP_START_JUMP);
}
gear = MovementDisplay.GEAR_JUMP;
}
} else if (ev.getActionCommand().equals(MOVE_SWIM)) {
if (gear != MovementDisplay.GEAR_SWIM) {
clearAllMoves();
}
// dcmd.addStep(MovePath.STEP_SWIM);
gear = MovementDisplay.GEAR_SWIM;
ce.setMovementMode((ce instanceof BipedMech) ? IEntityMovementMode.BIPED_SWIM : IEntityMovementMode.QUAD_SWIM);
} else if (ev.getActionCommand().equals(MOVE_TURN)) {
gear = MovementDisplay.GEAR_TURN;
} else if (ev.getActionCommand().equals(MOVE_BACK_UP)) {
if (gear == MovementDisplay.GEAR_JUMP) {
clearAllMoves();
}
gear = MovementDisplay.GEAR_BACKUP;
} else if (ev.getActionCommand().equals(MOVE_CLEAR)) {
clearAllMoves();
if (!client.game.containsMinefield(ce.getPosition())) {
clientgui.doAlertDialog(Messages.getString("MovementDisplay.CantClearMinefield"), //$NON-NLS-1$
Messages.getString("MovementDisplay.NoMinefield")); //$NON-NLS-1$
return;
}
int clear = Minefield.CLEAR_NUMBER_INFANTRY;
int boom = Minefield.CLEAR_NUMBER_INFANTRY_ACCIDENT;
// Does the entity has a minesweeper?
//TODO: not the way this is handled anymore, need to know whether they are specially trained
/*
for (Mounted mounted : ce.getMisc()) {
if (mounted.getType().hasFlag(MiscType.F_TOOLS) && mounted.getType().hasSubType(MiscType.S_MINESWEEPER)) {
int sweeperType = mounted.getType().getToHitModifier();
clear = Minefield.CLEAR_NUMBER_SWEEPER[sweeperType];
boom = Minefield.CLEAR_NUMBER_SWEEPER_ACCIDENT[sweeperType];
break;
}
}
*/
//need to choose a mine
Vector<Minefield> mfs = client.game.getMinefields(ce.getPosition());
String[] choices = new String[mfs.size()];
for (int loop = 0; loop < choices.length; loop++) {
choices[loop] = Minefield.getDisplayableName(mfs.elementAt(loop).getType());
}
SingleChoiceDialog choiceDialog = new SingleChoiceDialog(clientgui.frame, Messages.getString("MovementDisplay.ChooseMinefieldDialog.title"), //$NON-NLS-1$
Messages.getString("MovementDisplay.ChooseMinefieldDialog.message"), choices);
choiceDialog.setVisible(true);
Minefield mf = null;
if (choiceDialog.getAnswer() == true) {
mf = mfs.elementAt(choiceDialog.getChoice());
}
if ((null != mf) && clientgui.doYesNoDialog(Messages.getString("MovementDisplay.ClearMinefieldDialog.title"), //$NON-NLS-1$
Messages.getString("MovementDisplay.ClearMinefieldDialog.message", new Object[] { //$NON-NLS-1$
new Integer(clear), new Integer(boom) }))) {
cmd.addStep(MovePath.STEP_CLEAR_MINEFIELD, mf);
moveTo(cmd);
}
} else if (ev.getActionCommand().equals(MOVE_CHARGE)) {
if (gear != MovementDisplay.GEAR_LAND) {
clearAllMoves();
}
gear = MovementDisplay.GEAR_CHARGE;
} else if (ev.getActionCommand().equals(MOVE_DFA)) {
if (gear != MovementDisplay.GEAR_JUMP) {
clearAllMoves();
}
gear = MovementDisplay.GEAR_DFA;
if (!cmd.isJumping()) {
cmd.addStep(MovePath.STEP_START_JUMP);
}
} else if (ev.getActionCommand().equals(MOVE_RAM)) {
if (gear != MovementDisplay.GEAR_LAND) {
clearAllMoves();
}
gear = MovementDisplay.GEAR_RAM;
} else if (ev.getActionCommand().equals(MOVE_GET_UP)) {
//if the unit has a hull down step
//then don't clear the moves
if(!cmd.contains(MovePath.STEP_HULL_DOWN)) {
clearAllMoves();
}
if (cmd.getFinalProne() || cmd.getFinalHullDown()) {
cmd.addStep(MovePath.STEP_GET_UP);
}
clientgui.bv.drawMovementData(ce, cmd);
}else if (ev.getActionCommand().equals(MOVE_CAREFUL_STAND)) {
clearAllMoves();
ce.setCarefulStand(true);
if (cmd.getFinalProne() || cmd.getFinalHullDown()) {
cmd.addStep(MovePath.STEP_CAREFUL_STAND);
}
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_GO_PRONE)) {
gear = MovementDisplay.GEAR_LAND;
if (!cmd.getFinalProne()) {
cmd.addStep(MovePath.STEP_GO_PRONE);
}
clientgui.bv.drawMovementData(ce, cmd);
butDone.setLabel(Messages.getString("MovementDisplay.Move")); //$NON-NLS-1$
} else if (ev.getActionCommand().equals(MOVE_HULL_DOWN)) {
gear = MovementDisplay.GEAR_LAND;
if (!cmd.getFinalHullDown()) {
cmd.addStep(MovePath.STEP_HULL_DOWN);
}
clientgui.bv.drawMovementData(ce, cmd);
butDone.setLabel(Messages.getString("MovementDisplay.Move")); //$NON-NLS-1$
} else if (ev.getActionCommand().equals(MOVE_FLEE) && clientgui.doYesNoDialog(Messages.getString("MovementDisplay.EscapeDialog.title"), Messages.getString("MovementDisplay.EscapeDialog.message"))) { //$NON-NLS-1$ //$NON-NLS-2$
clearAllMoves();
cmd.addStep(MovePath.STEP_FLEE);
moveTo(cmd);
} else if (ev.getActionCommand().equals(MOVE_EJECT)) {
if (ce instanceof Tank) {
if (clientgui.doYesNoDialog(Messages.getString("MovementDisplay.AbandonDialog.title"), Messages.getString("MovementDisplay.AbandonDialog.message"))) { //$NON-NLS-1$ //$NON-NLS-2$
clearAllMoves();
cmd.addStep(MovePath.STEP_EJECT);
moveTo(cmd);
}
} else if (clientgui.doYesNoDialog(Messages.getString("MovementDisplay.AbandonDialog1.title"), Messages.getString("MovementDisplay.AbandonDialog1.message"))) { //$NON-NLS-1$ //$NON-NLS-2$
clearAllMoves();
cmd.addStep(MovePath.STEP_EJECT);
moveTo(cmd);
}
} else if (ev.getActionCommand().equals(MOVE_LOAD)) {
// Find the other friendly unit in our hex, add it
// to our local list of loaded units, and then stop.
Entity other = null;
Enumeration<Entity> entities = client.game.getEntities(ce.getPosition());
while (entities.hasMoreElements()) {
other = entities.nextElement();
if (!ce.getOwner().isEnemyOf(other.getOwner()) && !ce.equals(other)) {
loadedUnits.addElement(other);
break;
}
other = null;
}
if (other != null) {
cmd.addStep(MovePath.STEP_LOAD);
clientgui.bv.drawMovementData(ce, cmd);
gear = MovementDisplay.GEAR_LAND;
} // else - didn't find a unit to load
} else if (ev.getActionCommand().equals(MOVE_UNLOAD)) {
// Ask the user if we're carrying multiple units.
Entity other = getUnloadedUnit();
if (other != null) {
cmd.addStep(MovePath.STEP_UNLOAD, other);
clientgui.bv.drawMovementData(ce, cmd);
} // else - Player canceled the unload.
} else if (ev.getActionCommand().equals(MOVE_RAISE_ELEVATION)) {
cmd.addStep(MovePath.STEP_UP);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_LOWER_ELEVATION)) {
// if this movement path goes down more than two altitudes
// then add acceleration.
// TODO: Is there somewhere better to put this?
if ((ce instanceof Aero) && (null != cmd.getLastStep())
&& (cmd.getLastStep().getNDown() == 1) && (cmd.getLastStep().getVelocity() < 12)
&& !(((Aero) ce).isSpheroid() || client.game.getPlanetaryConditions().isVacuum())) {
cmd.addStep(MovePath.STEP_ACC, true);
}
cmd.addStep(MovePath.STEP_DOWN);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_CLIMB_MODE)) {
MoveStep ms = cmd.getLastStep();
if ((ms != null) && ((ms.getType() == MovePath.STEP_CLIMB_MODE_ON) || (ms.getType() == MovePath.STEP_CLIMB_MODE_OFF))) {
cmd.removeLastStep();
} else if (cmd.getFinalClimbMode()) {
cmd.addStep(MovePath.STEP_CLIMB_MODE_OFF);
} else {
cmd.addStep(MovePath.STEP_CLIMB_MODE_ON);
}
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_LAY_MINE)) {
int i = chooseMineToLay();
if (i != -1) {
Mounted m = ce().getEquipment(i);
if (m.getMineType() == Mounted.MINE_VIBRABOMB) {
VibrabombSettingDialog vsd = new VibrabombSettingDialog(clientgui.frame);
vsd.setVisible(true);
m.setVibraSetting(vsd.getSetting());
}
cmd.addStep(MovePath.STEP_LAY_MINE, i);
clientgui.bv.drawMovementData(ce, cmd);
}
} else if (ev.getActionCommand().equals(MOVE_DIG_IN)) {
cmd.addStep(MovePath.STEP_DIG_IN);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_FORTIFY)) {
cmd.addStep(MovePath.STEP_FORTIFY);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_SHAKE_OFF)) {
cmd.addStep(MovePath.STEP_SHAKE_OFF_SWARMERS);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_MODE_MECH)) {
clearAllMoves();
if (ce instanceof LandAirMech) {
final LandAirMech lam = (LandAirMech) client.getEntity(ce.getId());
lam.convertToMode(LandAirMech.MODE_MECH);
updateTransformationButtons(lam);
clientgui.mechD.displayEntity(lam);
}
} else if (ev.getActionCommand().equals(MOVE_MODE_AIRMECH)) {
clearAllMoves();
if (ce instanceof LandAirMech) {
final LandAirMech lam = (LandAirMech) client.getEntity(ce.getId());
lam.convertToMode(LandAirMech.MODE_AIRMECH);
updateTransformationButtons(lam);
clientgui.mechD.displayEntity(lam);
}
} else if (ev.getActionCommand().equals(MOVE_MODE_AIRCRAFT)) {
clearAllMoves();
if (ce instanceof LandAirMech) {
final LandAirMech lam = (LandAirMech) client.getEntity(ce.getId());
lam.convertToMode(LandAirMech.MODE_AIRCRAFT);
updateTransformationButtons(lam);
clientgui.mechD.displayEntity(lam);
}
} else if (ev.getActionCommand().equals(MOVE_RECKLESS)) {
cmd.setCareful(false);
} else if (ev.getActionCommand().equals(MOVE_ACCN)) {
cmd.addStep(MovePath.STEP_ACCN);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_DECN)) {
cmd.addStep(MovePath.STEP_DECN);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_ACC)) {
cmd.addStep(MovePath.STEP_ACC);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_DEC)) {
cmd.addStep(MovePath.STEP_DEC);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_EVADE)) {
cmd.addStep(MovePath.STEP_EVADE);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_EVADE_AERO)) {
cmd.addStep(MovePath.STEP_EVADE);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_ROLL)) {
cmd.addStep(MovePath.STEP_ROLL);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_HOVER)) {
cmd.addStep(MovePath.STEP_HOVER);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_MANEUVER)) {
ManeuverChoiceDialog choiceDialog = new ManeuverChoiceDialog(clientgui.frame, Messages.getString("MovementDisplay.ManeuverDialog.title"), //$NON-NLS-1$
"huh?");
Aero a = (Aero) ce;
MoveStep last = cmd.getLastStep();
int vel = a.getCurrentVelocity();
int elev = a.getElevation();
Coords pos = a.getPosition();
int distance = 0;
if (null != last) {
vel = last.getVelocityLeft();
elev = last.getElevation();
pos = last.getPosition();
distance = last.getDistance();
}
int ceil = client.game.getBoard().getHex(pos).ceiling();
choiceDialog.checkPerformability(vel, elev, ceil, a.isVSTOL(), distance);
choiceDialog.setVisible(true);
int manType = choiceDialog.getChoice();
if ((manType > ManeuverType.MAN_NONE) && addManeuver(manType)) {
clientgui.bv.drawMovementData(ce, cmd);
}
} else if (ev.getActionCommand().equals(MOVE_LAUNCH)) {
TreeMap<Integer, Vector<Integer>> launched = getLaunchedUnits();
if(!launched.isEmpty()) {
cmd.addStep(MovePath.STEP_LAUNCH, launched);
clientgui.bv.drawMovementData(ce, cmd);
}
} else if (ev.getActionCommand().equals(MOVE_RECOVER)) {
// if more than one unit is available as a carrier
// then bring up an option dialog
int recoverer = getRecoveryUnit();
if (recoverer != -1) {
cmd.addStep(MovePath.STEP_RECOVER, recoverer, -1);
clientgui.bv.drawMovementData(ce, cmd);
}
} else if (ev.getActionCommand().equals(MOVE_JOIN)) {
// if more than one unit is available as a carrier
// then bring up an option dialog
int joined = getUnitJoined();
if (joined != -1) {
cmd.addStep(MovePath.STEP_JOIN, joined, -1);
clientgui.bv.drawMovementData(ce, cmd);
}
} else if (ev.getActionCommand().equals(MOVE_TURN_LEFT)) {
cmd.addStep(MovePath.STEP_TURN_LEFT);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_TURN_RIGHT)) {
cmd.addStep(MovePath.STEP_TURN_RIGHT);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_THRUST)) {
cmd.addStep(MovePath.STEP_THRUST);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_YAW)) {
cmd.addStep(MovePath.STEP_YAW);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_END_OVER)) {
cmd.addStep(MovePath.STEP_YAW);
cmd.addStep(MovePath.STEP_ROLL);
clientgui.bv.drawMovementData(ce, cmd);
} else if (ev.getActionCommand().equals(MOVE_DUMP)) {
dumpBombs();
}
updateProneButtons();
updateRACButton();
updateSearchlightButton();
updateLoadButtons();
updateElevationButtons();
updateFleeButton();
updateLaunchButton();
updateRecklessButton();
updateHoverButton();
updateManeuverButton();
updateDumpButton();
updateSpeedButtons();
updateThrustButton();
updateRollButton();
checkFuel();
checkOOC();
checkAtmosphere();
}
/**
* Give the player the opportunity to unload all entities that are stranded
* on immobile transports. <p/> According to <a
* href="http://www.classicbattletech.com/w3t/showflat.php?Cat=&Board=ask&Number=555466&page=2&view=collapsed&sb=5&o=0&fpart=">
* Randall Bills</a>, the "minimum move" rule allow stranded units to
* dismount at the start of the turn.
*/
private void unloadStranded() {
Vector<Entity> stranded = new Vector<Entity>();
String[] names = null;
Entity entity = null;
Entity transport = null;
// Let the player know what's going on.
setStatusBarText(Messages.getString("MovementDisplay.AllPlayersUnload")); //$NON-NLS-1$
// Collect the stranded entities into the vector.
// TODO : get a better interface to "game" and "turn"
Enumeration<Entity> entities = client.getSelectedEntities(new EntitySelector() {
private final IGame game = client.game;
private final GameTurn turn = client.game.getTurn();
private final int ownerId = client.getLocalPlayer().getId();
public boolean accept(Entity entity) {
if (turn.isValid(ownerId, entity, game)) {
return true;
}
return false;
}
});
while (entities.hasMoreElements()) {
stranded.addElement(entities.nextElement());
}
// Construct an array of stranded entity names
names = new String[stranded.size()];
for (int index = 0; index < names.length; index++) {
entity = stranded.elementAt(index);
transport = client.getEntity(entity.getTransportId());
String buffer;
if (null == transport) {
buffer = entity.getDisplayName();
} else {
buffer = Messages.getString("MovementDisplay.EntityAt", new Object[] { entity.getDisplayName(), transport.getPosition().getBoardNum() }); //$NON-NLS-1$
}
names[index] = buffer.toString();
}
// Show the choices to the player
int[] indexes = clientgui.doChoiceDialog(Messages.getString("MovementDisplay.UnloadStrandedUnitsDialog.title"), //$NON-NLS-1$
Messages.getString("MovementDisplay.UnloadStrandedUnitsDialog.message"), //$NON-NLS-1$
names);
// Convert the indexes into selected entity IDs and tell the server.
int[] ids = null;
if (null != indexes) {
ids = new int[indexes.length];
for (int index = 0; index < indexes.length; index++) {
entity = stranded.elementAt(index);
ids[index] = entity.getId();
}
}
client.sendUnloadStranded(ids);
}
//
// KeyListener
//
public void keyPressed(KeyEvent ev) {
final Entity ce = ce();
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
if (ev.getKeyCode() == KeyEvent.VK_ESCAPE) {
clearAllMoves();
}
if (ev.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
if (client.isMyTurn()) {
removeLastStep();
}
}
if ((ev.getKeyCode() == KeyEvent.VK_ENTER) && ev.isControlDown()) {
if (client.isMyTurn()) {
moveTo(cmd);
}
}
if ((ev.getKeyCode() == KeyEvent.VK_SHIFT) && !shiftheld) {
shiftheld = true;
if (client.isMyTurn() && (clientgui.getBoardView().getLastCursor() != null) && !clientgui.getBoardView().getLastCursor().equals(clientgui.getBoardView().getSelected())) {
// switch to turning
// clientgui.bv.clearMovementData();
currentMove(clientgui.getBoardView().getLastCursor());
clientgui.bv.drawMovementData(ce, cmd);
}
}
// arrow can also rotate when shift is down
if (shiftheld && client.isMyTurn() && ((ev.getKeyCode() == KeyEvent.VK_LEFT) || (ev.getKeyCode() == KeyEvent.VK_RIGHT))) {
int curDir = cmd.getFinalFacing();
int dir = curDir;
if (ev.getKeyCode() == KeyEvent.VK_LEFT) {
dir = (dir + 5) % 6;
} else {
dir = (dir + 7) % 6;
}
Coords curPos = cmd.getFinalCoords();
Coords target = curPos.translated(dir);
currentMove(target);
clientgui.bv.drawMovementData(ce, cmd);
}
}
public void keyReleased(KeyEvent ev) {
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
if ((ev.getKeyCode() == KeyEvent.VK_SHIFT) && shiftheld) {
shiftheld = false;
if (client.isMyTurn() && (clientgui.getBoardView().getLastCursor() != null) && !clientgui.getBoardView().getLastCursor().equals(clientgui.getBoardView().getSelected())) {
// switch to movement
clientgui.bv.clearMovementData();
currentMove(clientgui.getBoardView().getLastCursor());
clientgui.bv.drawMovementData(ce(), cmd);
}
}
}
public void keyTyped(KeyEvent ev) {
}
// board view listener
@Override
public void finishedMovingUnits(BoardViewEvent b) {
final Entity ce = ce();
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
if (client.isMyTurn() && (ce != null)) {
clientgui.setDisplayVisible(true);
clientgui.bv.centerOnHex(ce.getPosition());
}
}
@Override
public void unitSelected(BoardViewEvent b) {
// Are we ignoring events?
if (isIgnoringEvents()) {
return;
}
Entity e = client.game.getEntity(b.getEntityId());
if (null == e) {
return;
}
if (client.isMyTurn()) {
if (client.game.getTurn().isValidEntity(e, client.game)) {
selectEntity(e.getId());
}
} else {
clientgui.setDisplayVisible(true);
clientgui.mechD.displayEntity(e);
if (e.isDeployed()) {
clientgui.bv.centerOnHex(e.getPosition());
}
}
}
private void setWalkEnabled(boolean enabled) {
butWalk.setEnabled(enabled);
clientgui.getMenuBar().setMoveWalkEnabled(enabled);
}
private void setTurnEnabled(boolean enabled) {
butTurn.setEnabled(enabled);
clientgui.getMenuBar().setMoveTurnEnabled(enabled);
}
private void setNextEnabled(boolean enabled) {
butNext.setEnabled(enabled);
clientgui.getMenuBar().setMoveNextEnabled(enabled);
}
private void setLayMineEnabled(boolean enabled) {
butLayMine.setEnabled(enabled);
clientgui.getMenuBar().setMoveLayMineEnabled(enabled);
}
private void setLoadEnabled(boolean enabled) {
butLoad.setEnabled(enabled);
clientgui.getMenuBar().setMoveLoadEnabled(enabled);
}
private void setUnloadEnabled(boolean enabled) {
butUnload.setEnabled(enabled);
clientgui.getMenuBar().setMoveUnloadEnabled(enabled);
}
private void setJumpEnabled(boolean enabled) {
butJump.setEnabled(enabled);
clientgui.getMenuBar().setMoveJumpEnabled(enabled);
}
private void setSwimEnabled(boolean enabled) {
butSwim.setEnabled(enabled);
clientgui.getMenuBar().setMoveSwimEnabled(enabled);
}
private void setBackUpEnabled(boolean enabled) {
butBackup.setEnabled(enabled);
clientgui.getMenuBar().setMoveBackUpEnabled(enabled);
}
private void setChargeEnabled(boolean enabled) {
butCharge.setEnabled(enabled);
clientgui.getMenuBar().setMoveChargeEnabled(enabled);
}
private void setDFAEnabled(boolean enabled) {
butDfa.setEnabled(enabled);
clientgui.getMenuBar().setMoveDFAEnabled(enabled);
}
private void setGoProneEnabled(boolean enabled) {
butDown.setEnabled(enabled);
clientgui.getMenuBar().setMoveGoProneEnabled(enabled);
}
private void setFleeEnabled(boolean enabled) {
butFlee.setEnabled(enabled);
clientgui.getMenuBar().setMoveFleeEnabled(enabled);
}
private void setEjectEnabled(boolean enabled) {
butEject.setEnabled(enabled);
clientgui.getMenuBar().setMoveEjectEnabled(enabled);
}
private void setUnjamEnabled(boolean enabled) {
butRAC.setEnabled(enabled);
clientgui.getMenuBar().setMoveUnjamEnabled(enabled);
}
private void setSearchlightEnabled(boolean enabled, boolean state) {
if (state) {
butSearchlight.setLabel(Messages.getString("MovementDisplay.butSearchlightOff")); //$NON-NLS-1$
} else {
butSearchlight.setLabel(Messages.getString("MovementDisplay.butSearchlightOn")); //$NON-NLS-1$
}
butSearchlight.setEnabled(enabled);
clientgui.getMenuBar().setMoveSearchlightEnabled(enabled);
}
private void setHullDownEnabled(boolean enabled) {
butHullDown.setEnabled(enabled);
clientgui.getMenuBar().setMoveHullDownEnabled(enabled);
}
private void setClearEnabled(boolean enabled) {
butClear.setEnabled(enabled);
clientgui.getMenuBar().setMoveClearEnabled(enabled);
}
private void setGetUpEnabled(boolean enabled) {
butUp.setEnabled(enabled);
clientgui.getMenuBar().setMoveGetUpEnabled(enabled);
}
private void setRaiseEnabled(boolean enabled) {
butRaise.setEnabled(enabled);
clientgui.getMenuBar().setMoveRaiseEnabled(enabled);
}
private void setLowerEnabled(boolean enabled) {
butLower.setEnabled(enabled);
clientgui.getMenuBar().setMoveLowerEnabled(enabled);
}
private void setRecklessEnabled(boolean enabled) {
butReckless.setEnabled(enabled);
clientgui.getMenuBar().setMoveRecklessEnabled(enabled);
}
private void setLAMmechModeEnabled(boolean enabled) {
clientgui.getMenuBar().setMoveLAMmechModeEnabled(enabled);
}
private void setLAMairmechModeEnabled(boolean enabled) {
clientgui.getMenuBar().setMoveLAMairmechModeEnabled(enabled);
}
private void setLAMaircraftModeEnabled(boolean enabled) {
clientgui.getMenuBar().setMoveLAMaircraftModeEnabled(enabled);
}
private void setAccEnabled(boolean enabled) {
butAcc.setEnabled(enabled);
clientgui.getMenuBar().setMoveAccEnabled(enabled);
}
private void setDecEnabled(boolean enabled) {
butDec.setEnabled(enabled);
clientgui.getMenuBar().setMoveDecEnabled(enabled);
}
private void setAccNEnabled(boolean enabled) {
butAccN.setEnabled(enabled);
clientgui.getMenuBar().setMoveAccNEnabled(enabled);
}
private void setDecNEnabled(boolean enabled) {
butDecN.setEnabled(enabled);
clientgui.getMenuBar().setMoveDecNEnabled(enabled);
}
private void setEvadeEnabled(boolean enabled) {
butEvade.setEnabled(enabled);
clientgui.getMenuBar().setMoveEvadeEnabled(enabled);
}
private void setEvadeAeroEnabled(boolean enabled) {
butEvadeAero.setEnabled(enabled);
clientgui.getMenuBar().setMoveEvadeAeroEnabled(enabled);
}
private void setRollEnabled(boolean enabled) {
butRoll.setEnabled(enabled);
clientgui.getMenuBar().setMoveRollEnabled(enabled);
}
private void setLaunchEnabled(boolean enabled) {
butLaunch.setEnabled(enabled);
clientgui.getMenuBar().setMoveLaunchEnabled(enabled);
}
private void setRecoverEnabled(boolean enabled) {
butRecover.setEnabled(enabled);
clientgui.getMenuBar().setMoveRecoverEnabled(enabled);
}
private void setJoinEnabled(boolean enabled) {
butJoin.setEnabled(enabled);
clientgui.getMenuBar().setMoveJoinEnabled(enabled);
}
private void setDumpEnabled(boolean enabled) {
butDump.setEnabled(enabled);
clientgui.getMenuBar().setMoveDumpEnabled(enabled);
}
private void setRamEnabled(boolean enabled) {
butRam.setEnabled(enabled);
clientgui.getMenuBar().setMoveRamEnabled(enabled);
}
private void setHoverEnabled(boolean enabled) {
butHover.setEnabled(enabled);
clientgui.getMenuBar().setMoveHoverEnabled(enabled);
}
private void setManeuverEnabled(boolean enabled) {
butManeuver.setEnabled(enabled);
clientgui.getMenuBar().setMoveManeuverEnabled(enabled);
}
private void setTurnLeftEnabled(boolean enabled) {
butTurnLeft.setEnabled(enabled);
clientgui.getMenuBar().setMoveTurnLeftEnabled(enabled);
}
private void setTurnRightEnabled(boolean enabled) {
butTurnRight.setEnabled(enabled);
clientgui.getMenuBar().setMoveTurnRightEnabled(enabled);
}
private void setThrustEnabled(boolean enabled) {
butThrust.setEnabled(enabled);
clientgui.getMenuBar().setMoveThrustEnabled(enabled);
}
private void setYawEnabled(boolean enabled) {
butYaw.setEnabled(enabled);
clientgui.getMenuBar().setMoveYawEnabled(enabled);
}
private void setEndOverEnabled(boolean enabled) {
butEndOver.setEnabled(enabled);
clientgui.getMenuBar().setMoveEndOverEnabled(enabled);
}
/**
* Retrieve the "Done" button of this object.
*
* @return the <code>java.awt.Button</code> that activates this object's
* "Done" action.
*/
public Button getDoneButton() {
return butDone;
}
/**
* Stop just ignoring events and actually stop listening to them.
*/
public void removeAllListeners() {
client.game.removeGameListener(this);
clientgui.getBoardView().removeBoardViewListener(this);
}
/*
* Add steps for advanced vector movement based on the given vectors when
* splitting hexes, choose the hex with less tonnage in case OOC
*/
private MovePath addSteps(MovePath md, Entity en) {
// if the last step is a launch or recovery, then I want to keep that at
// the end
MoveStep lastStep = md.getLastStep();
if ((lastStep != null) && ((lastStep.getType() == MovePath.STEP_LAUNCH) || (lastStep.getType() == MovePath.STEP_RECOVER))) {
md.removeLastStep();
}
// get the start and end
Coords start = en.getPosition();
Coords end = Compute.getFinalPosition(start, md.getFinalVectors());
// Coords end = md.getFinalVectors().getFinalPosition(start);
// (see LosEffects.java)
ArrayList<Coords> in = Coords.intervening(start, end);
// first check whether we are splitting hexes
boolean split = false;
double degree = start.degree(end);
if (degree % 60 == 30) {
split = true;
in = Coords.intervening(start, end, true);
}
Coords current = start;
int facing = md.getFinalFacing();
for (int i = 1; i < in.size(); i++) {
// check for split hexes
// check for some number after a multiple of 3 (1,4,7,etc)
if (((i % 3) == 1) && split) {
Coords left = in.get(i);
Coords right = in.get(i + 1);
// get the total tonnage in each hex
Enumeration<Entity> leftTargets = client.game.getEntities(left);
double leftTonnage = 0;
while (leftTargets.hasMoreElements()) {
leftTonnage += leftTargets.nextElement().getWeight();
}
Enumeration<Entity> rightTargets = client.game.getEntities(right);
double rightTonnage = 0;
while (rightTargets.hasMoreElements()) {
rightTonnage += rightTargets.nextElement().getWeight();
}
// TODO: I will need to update this to account for asteroids
// I need to consider both of these passed through
// for purposes of bombing
en.addPassedThrough(right);
en.addPassedThrough(left);
client.sendUpdateEntity(en);
// if the left is preferred, increment i so next one is skipped
if (leftTonnage < rightTonnage) {
i++;
} else {
continue;
}
}
Coords c = in.get(i);
// check if the next move would put vessel off the map
if (!client.game.getBoard().contains(c)) {
md.addStep(MovePath.STEP_OFF);
break;
}
// which direction is this from the current hex?
int dir = current.direction(c);
// what kind of step do I need to get there?
int diff = dir - facing;
if (diff == 0) {
md.addStep(MovePath.STEP_FORWARDS);
} else if ((diff == 1) || (diff == -5)) {
md.addStep(MovePath.STEP_LATERAL_RIGHT);
} else if ((diff == -2) || (diff == 4)) {
md.addStep(MovePath.STEP_LATERAL_RIGHT_BACKWARDS);
} else if ((diff == -1) || (diff == 5)) {
md.addStep(MovePath.STEP_LATERAL_LEFT);
} else if ((diff == 2) || (diff == -4)) {
md.addStep(MovePath.STEP_LATERAL_LEFT_BACKWARDS);
} else if ((diff == 3) || (diff == -3)) {
md.addStep(MovePath.STEP_BACKWARDS);
}
current = c;
}
// do I now need to add on the last step again?
if ((lastStep != null) && (lastStep.getType() == MovePath.STEP_LAUNCH)) {
md.addStep(MovePath.STEP_LAUNCH, lastStep.getLaunched());
}
if ((lastStep != null) && (lastStep.getType() == MovePath.STEP_RECOVER)) {
md.addStep(MovePath.STEP_RECOVER, lastStep.getRecoveryUnit());
}
return md;
}
}