📄 compute.java
字号:
*/ if (((prevStepIsOnPavement && movementType == IEntityMovementType.MOVE_RUN) || (srcHex.containsTerrain(Terrains.ICE)) && movementType != IEntityMovementType.MOVE_JUMP) && isTurning && !isInfantry) { return true; } // If we entering or leaving a building, all non-infantry // need to make a piloting check to avoid damage. // TODO: allow entities to occupy different levels of buildings. if ((srcElevation < srcHex.terrainLevel(Terrains.BLDG_ELEV) || destElevation < destHex .terrainLevel(Terrains.BLDG_ELEV)) && !(entity instanceof Infantry)) { return true; } // check sideslips if (entity instanceof VTOL) { if (isTurning && ((movementType == IEntityMovementType.MOVE_RUN) || (movementType == IEntityMovementType.MOVE_VTOL_RUN))) return true; } return false; } /** * Can the defending unit be displaced from the source to the destination? */ public static boolean isValidDisplacement(IGame game, int entityId, Coords src, int direction) { return isValidDisplacement(game, entityId, src, src .translated(direction)); } /** * Can the defending unit be displaced from the source to the destination? */ public static boolean isValidDisplacement(IGame game, int entityId, Coords src, Coords dest) { final Entity entity = game.getEntity(entityId); final IHex srcHex = game.getBoard().getHex(src); final IHex destHex = game.getBoard().getHex(dest); final ArrayList<Coords> intervening = Coords.intervening(src, dest); final int direction = src.direction(dest); // arguments valid? if (entity == null) { throw new IllegalArgumentException("Entity invalid."); } // an easy check if (!game.getBoard().contains(dest)) { if (game.getOptions().booleanOption("push_off_board")) { return true; } return false; } // can't be displaced into prohibited terrain // unless we're displacing a tracked or wheeled vee into water if (entity.isHexProhibited(destHex) && !(entity instanceof Tank && destHex.containsTerrain(Terrains.WATER) && (entity.movementMode == IEntityMovementMode.TRACKED || entity.movementMode == IEntityMovementMode.WHEELED))) { return false; } // can't go up more levels than normally possible for (Coords c : intervening) { final IHex hex = game.getBoard().getHex(c); int change = entity.elevationOccupied(hex) - entity.elevationOccupied(srcHex); if (change > entity.getMaxElevationChange()) { return false; } } // if there's an entity in the way, can they be displaced in that // direction? Entity inTheWay = stackingViolation(game, entityId, dest); if (inTheWay != null) { return isValidDisplacement(game, inTheWay.getId(), inTheWay .getPosition(), direction); } // okay, that's about all the checks return true; } /** * Gets a valid displacement, from the hexes around src, as close to the * original direction as is possible. * * @return valid displacement coords, or null if none */ public static Coords getValidDisplacement(IGame game, int entityId, Coords src, int direction) { // check the surrounding hexes, nearest to the original direction first int[] offsets = { 0, 1, 5, 2, 4, 3 }; for (int i = 0; i < offsets.length; i++) { Coords dest = src.translated((direction + offsets[i]) % 6); if (isValidDisplacement(game, entityId, src, dest)) { return dest; } } // have fun being insta-killed! return null; } /** * Gets a preferred displacement. Right now this picks the surrounding hex * with the highest elevation that is a valid displacement. * * @return valid displacement coords, or null if none */ public static Coords getPreferredDisplacement(IGame game, int entityId, Coords src, int direction) { final Entity entity = game.getEntity(entityId); int highestElev = Integer.MIN_VALUE; Coords highest = null; // check the surrounding hexes, nearest to the original direction first int[] offsets = { 0, 1, 5, 2, 4, 3 }; for (int i = 0; i < offsets.length; i++) { Coords dest = src.translated((direction + offsets[i]) % 6); if (isValidDisplacement(game, entityId, src, dest) && game.getBoard().contains(dest)) { IHex hex = game.getBoard().getHex(dest); int elevation = entity.elevationOccupied(hex); if (elevation > highestElev) { highestElev = elevation; highest = dest; } // preferably, go to same elevation if (elevation == entity.getElevation()) { return dest; } } } return highest; } /** * Gets a hex to displace a missed charge to. Picks left or right, first * preferring higher hexes, then randomly, or returns the base hex if * they're impassible. */ public static Coords getMissedChargeDisplacement(IGame game, int entityId, Coords src, int direction) { Coords first = src.translated((direction + 1) % 6); Coords second = src.translated((direction + 5) % 6); IHex firstHex = game.getBoard().getHex(first); IHex secondHex = game.getBoard().getHex(second); Entity entity = game.getEntity(entityId); if (firstHex == null || secondHex == null) { // leave it, will be handled } else if (entity.elevationOccupied(firstHex) > entity .elevationOccupied(secondHex)) { // leave it } else if (entity.elevationOccupied(firstHex) < entity .elevationOccupied(secondHex)) { // switch Coords temp = first; first = second; second = temp; } else if (Compute.d6() > 3) { // switch randomly Coords temp = first; first = second; second = temp; } if (isValidDisplacement(game, entityId, src, src.direction(first)) && game.getBoard().contains(first)) { return first; } else if (isValidDisplacement(game, entityId, src, src .direction(second)) && game.getBoard().contains(second)) { return second; } else { return src; } } /** * Finds the best spotter for the attacker. The best spotter is the one with * the lowest attack modifiers, of course. LOS modifiers and movement are * considered. */ public static Entity findSpotter(IGame game, Entity attacker, Targetable target) { Entity spotter = null; int taggedBy = -1; if (target instanceof Entity) { taggedBy = ((Entity)target).getTaggedBy(); } ToHitData bestMods = new ToHitData(ToHitData.IMPOSSIBLE, ""); for (java.util.Enumeration i = game.getEntities(); i.hasMoreElements();) { Entity other = (Entity) i.nextElement(); if ( (other.isSpotting() || taggedBy == other.getId() ) && !attacker.isEnemyOf(other)) { // what are this guy's mods to the attack? LosEffects los = LosEffects.calculateLos(game, other.getId(), target); ToHitData mods = los.losModifiers(game); los.setTargetCover(LosEffects.COVER_NONE); mods.append(getAttackerMovementModifier(game, other.getId())); // is this guy a better spotter? if (spotter == null || mods.getValue() < bestMods.getValue()) { spotter = other; bestMods = mods; } } } return spotter; } public static ToHitData getImmobileMod(Targetable target) { return getImmobileMod(target, Mech.LOC_NONE, IAimingModes.AIM_MODE_NONE); } public static ToHitData getImmobileMod(Targetable target, int aimingAt, int aimingMode) { if (target.isImmobile()) { if (target instanceof Mech && aimingAt == Mech.LOC_HEAD && aimingMode == IAimingModes.AIM_MODE_IMMOBILE) { return new ToHitData(3, "aiming at head"); } return new ToHitData(-4, "target immobile"); } return null; } /** * Determines the to-hit modifier due to range for an attack with the * specified parameters. Includes minimum range, infantry 0-range mods, and * target stealth mods. Accounts for friendly C3 units. * * @return the modifiers */ public static ToHitData getRangeMods(IGame game, Entity ae, int weaponId, Targetable target) { Mounted weapon = ae.getEquipment(weaponId); WeaponType wtype = (WeaponType) weapon.getType(); int[] weaponRanges = wtype.getRanges(); boolean isAttackerInfantry = (ae instanceof Infantry); boolean isWeaponInfantry = wtype.hasFlag(WeaponType.F_INFANTRY); boolean isLRMInfantry = isWeaponInfantry && wtype.getAmmoType() == AmmoType.T_LRM; boolean isIndirect = ((wtype.getAmmoType() == AmmoType.T_LRM) || (wtype.getAmmoType() == AmmoType.T_EXLRM) || (wtype.getAmmoType() == AmmoType.T_TBOLT5) || (wtype.getAmmoType() == AmmoType.T_TBOLT10) || (wtype.getAmmoType() == AmmoType.T_TBOLT15) || (wtype.getAmmoType() == AmmoType.T_TBOLT20) || (wtype.getAmmoType() == AmmoType.T_LRM_TORPEDO)) && weapon.curMode().equals("Indirect"); boolean useExtremeRange = game.getOptions().booleanOption( "maxtech_range"); ToHitData mods = new ToHitData(); // modify the ranges for ATM missile systems based on the ammo selected // TODO: this is not the right place to hardcode these if (wtype.getAmmoType() == AmmoType.T_ATM) { AmmoType atype = (AmmoType) weapon.getLinked().getType(); if ((atype.getAmmoType() == AmmoType.T_ATM) && atype.getMunitionType() == AmmoType.M_EXTENDED_RANGE) { weaponRanges = new int[] { 4, 9, 18, 27, 36 }; } else if ((atype.getAmmoType() == AmmoType.T_ATM) && atype.getMunitionType() == AmmoType.M_HIGH_EXPLOSIVE) { weaponRanges = new int[] { 0, 3, 6, 9, 12 }; } } // // modifiy the ranges for PPCs when field inhibitors are turned off // TODO: See above, it should be coded elsewhere... // if (wtype.getName().equals("Particle Cannon")) { if (game.getOptions().booleanOption("maxtech_ppc_inhibitors")) { if (weapon.curMode().equals("Field Inhibitor OFF")) { weaponRanges[0] = 0; } } } //Hotloaded weapons if ( weapon.isHotLoaded() && game.getOptions().booleanOption("maxtech_hotload") ) weaponRanges[RangeType.RANGE_MINIMUM] = 0; // is water involved? IHex attHex = game.getBoard().getHex(ae.getPosition()); IHex targHex = game.getBoard().getHex(target.getPosition()); int targTop = 0; int targBottom = 0; if (target != null) { targTop = target.absHeight(); targBottom = target.getElevation(); } boolean targetInPartialWater = false; boolean targetUnderwater = false; boolean weaponUnderwater = (ae.getLocationStatus(weapon.getLocation()) == ILocationExposureStatus.WET); if (targHex.containsTerrain(Terrains.WATER) && targBottom < 0) { if (targTop >= 0) targetInPartialWater = true; else targetUnderwater = true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -