📄 movepath.java
字号:
/** * 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.common;import java.util.Comparator;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.io.Serializable;import java.util.Enumeration;import java.util.Vector;import megamek.common.preference.PreferenceManager;/** * Holds movement path for an entity. */public class MovePath implements Cloneable, Serializable { public static final int STEP_FORWARDS = 1; public static final int STEP_BACKWARDS = 2; public static final int STEP_TURN_LEFT = 3; public static final int STEP_TURN_RIGHT = 4; public static final int STEP_GET_UP = 5; public static final int STEP_GO_PRONE = 6; public static final int STEP_START_JUMP = 7; public static final int STEP_CHARGE = 8; public static final int STEP_DFA = 9; public static final int STEP_FLEE = 10; public static final int STEP_LATERAL_LEFT = 11; public static final int STEP_LATERAL_RIGHT = 12; public static final int STEP_LATERAL_LEFT_BACKWARDS = 13; public static final int STEP_LATERAL_RIGHT_BACKWARDS = 14; public static final int STEP_UNJAM_RAC = 15; public static final int STEP_LOAD = 16; public static final int STEP_UNLOAD = 17; public static final int STEP_EJECT = 18; public static final int STEP_CLEAR_MINEFIELD = 19; public static final int STEP_UP = 20; public static final int STEP_DOWN = 21; public static final int STEP_SEARCHLIGHT = 22; public static final int STEP_LAY_MINE = 23; public static final int STEP_HULL_DOWN = 24; public static final int STEP_CLIMB_MODE_ON = 25; public static final int STEP_CLIMB_MODE_OFF = 26; public static final int STEP_SWIM = 27; public static final int STEP_DIG_IN = 28; public static final int STEP_FORTIFY = 29; public static class Key { private Coords coords; private int facing; private int type; public Key(Coords coords, int facing, int type) { this.coords = coords; this.facing = facing; this.type = type; } public boolean equals(Object obj) { Key s1 = (Key) obj; if (s1 != null) { return type == type && facing == s1.facing && coords.equals(s1.coords); } return false; } public int hashCode() { return type + 7 * (facing + 31 * coords.hashCode()); } } protected Vector steps = new Vector(); protected transient IGame game; protected transient Entity entity; public static final int DEFAULT_PATHFINDER_TIME_LIMIT = 2000; /** * Generates a new, empty, movement path object. */ public MovePath(IGame game, Entity entity) { this.entity = entity; this.game = game; } public Entity getEntity() { return entity; } public Key getKey() { return new Key(getFinalCoords(), getFinalFacing(), getFinalProne()?0:isJumping()?1:2); } public String toString() { StringBuffer sb = new StringBuffer(); for (Enumeration i = steps.elements(); i.hasMoreElements();) { sb.append(i.nextElement().toString()); sb.append(' '); } return sb.toString(); } /** * Returns the number of steps in this movement */ public int length() { return steps.size(); } /** * Add a new step to the movement path. * * @param type the type of movement. */ public MovePath addStep(int type) { // TODO : detect steps off the map *here*. return addStep( new MoveStep( this, type ) ); } /** * Add a new step to the movement path with the given target. * * @param type the type of movement. * @param target the <code>Targetable</code> object that is the target of * this step. For example, the enemy being charged. */ public MovePath addStep(int type, Targetable target) { return addStep(new MoveStep(this, type, target)); } public MovePath addStep(int type, int mineToLay) { return addStep(new MoveStep(this, type, mineToLay)); } public boolean canShift() { return ((entity instanceof QuadMech) || entity.isUsingManAce()) && !isJumping(); } /** * Initializes a step as part of this movement path. Then adds it to the * list. * * @param step */ protected MovePath addStep(MoveStep step) { steps.addElement(step); // transform lateral shifts for quads or maneuverability aces if (canShift()) { transformLateralShift(); } MoveStep prev = getStep(steps.size() - 2); try { step.compile(game, entity, prev); } catch (RuntimeException re) {// // N.B. the pathfinding will try steps off the map.// re.printStackTrace(); step.setMovementType(IEntityMovementType.MOVE_ILLEGAL); } // check for illegal jumps Coords start = entity.getPosition(); Coords land = step.getPosition(); int distance = start.distance(land); if (isJumping()) { if (step.getMpUsed() > distance) { step.setMovementType(IEntityMovementType.MOVE_ILLEGAL); } } // If the new step is legal and is a different position than // the previous step, then update the older steps, letting // them know that they are no longer the end of the path. if ( step.isLegal() && null != prev && !land.equals( prev.getPosition() ) ) { // Loop through the steps from back to front. // Stop looping when the step says to, or we run out of steps. int index = steps.size() - 2; while ( index >= 0 && getStep( index ).setEndPos( false ) ) index--; } // End step-is-legal return this; } public void compile(IGame g, Entity en) { this.game = g; this.entity = en; Vector temp = (Vector) steps.clone(); steps.removeAllElements(); for (int i = 0; i < temp.size(); i++) { MoveStep step = (MoveStep) temp.elementAt(i); if (step.getTarget(game) != null) { step = new MoveStep(this, step.getType(), step.getTarget(game)); } else if (step.getMineToLay() != -1){ step = new MoveStep(this, step.getType(), step.getMineToLay()); } else { step = new MoveStep(this, step.getType()); } this.addStep(step); } clipToPossible(); } public void removeLastStep() { if (steps.size() > 0) { steps.removeElementAt(steps.size() - 1); } // Find the new last step in the path. int index = steps.size() - 1; while ( index >= 0 && getStep( index ).setEndPos( true ) && !getStep( index ).isLegal() ) index--; } public void clear() { steps.removeAllElements(); } public Enumeration getSteps() { return steps.elements(); } public MoveStep getStep(int index) { if (index < 0 || index >= steps.size()) { return null; } return (MoveStep) steps.elementAt(index); } /** * Check for any of the specified type of step in the path */ public boolean contains(int type) { for (final Enumeration i = getSteps(); i.hasMoreElements();) { MoveStep step = (MoveStep) i.nextElement(); if (step.getType() == type) { return true; } } return false; } /** * Check for MASC use */ public boolean hasActiveMASC() { for (final Enumeration i = getSteps(); i.hasMoreElements();) { MoveStep step = (MoveStep) i.nextElement(); if (step.isUsingMASC()) { return true; } } return false; } /** * Returns the final coordinates if a mech were to perform all the steps in * this path. */ public Coords getFinalCoords() { if (getLastStep() != null) { return getLastStep().getPosition(); } return entity.getPosition(); } /** * Returns the final facing if a mech were to perform all the steps in this * path. */ public int getFinalFacing() { if (getLastStep() != null) { return getLastStep().getFacing(); } return entity.getFacing(); } /** * Returns whether or not a unit would end up prone after all of the steps */ public boolean getFinalProne() { if (getLastStep() != null) { return getLastStep().isProne(); } if (entity == null) return false; return entity.isProne(); } /** * Returns whether or not a unit would end up prone after all of the steps */ public boolean getFinalHullDown() { if (getLastStep() != null) { return getLastStep().isHullDown(); } if (entity == null) return false; return entity.isHullDown(); } /** * Returns whether or not a unit would be in climb mode after all the steps */ public boolean getFinalClimbMode() { if (getLastStep() != null) { return getLastStep().climbMode(); } if (entity == null) return false; return entity.climbMode(); } /** * get final elevation relative to the hex. */ public int getFinalElevation() { if (getLastStep() != null) { return getLastStep().getElevation(); } return entity.getElevation(); } public int getLastStepMovementType() { if (getLastStep() == null) { return IEntityMovementType.MOVE_NONE; } return getLastStep().getMovementType(); } public MoveStep getLastStep() { return getStep(steps.size() - 1); } public MoveStep getSecondLastStep() { if (steps.size() > 1) { return getStep(steps.size() - 2); } return getLastStep(); } /* Debug method */ public void printAllSteps() { System.out.println("*Steps*"); for (int i = 0; i < steps.size(); i++) { System.out.println(" " + i + ": " + getStep(i) + ", " + getStep(i).getMovementType()); } } /** * Removes impossible steps. */ public void clipToPossible() { // hopefully there's no impossible steps in the middle of possible ones Vector goodSteps = new Vector(); for (final Enumeration i = steps.elements(); i.hasMoreElements();) { final MoveStep step = (MoveStep) i.nextElement(); if (step.getMovementType() != IEntityMovementType.MOVE_ILLEGAL) { goodSteps.addElement(step); } } steps = goodSteps; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -