diff --git a/megamek/i18n/megamek/common/options/messages.properties b/megamek/i18n/megamek/common/options/messages.properties index a500c422052..7a15487ba48 100644 --- a/megamek/i18n/megamek/common/options/messages.properties +++ b/megamek/i18n/megamek/common/options/messages.properties @@ -534,6 +534,8 @@ PilotOptionsInfo.option.animal_mimic.displayableName=Animal Mimicry (CamOps) PilotOptionsInfo.option.animal_mimic.description=Allows a Quad Mek or ProtoMek, or a bipedal Mek or ProtoMek with the animalistic quirk, the following benefits.\n-1 MP per hex of Woods and Jungle terrain.\n In addition quads gain a -1 to any quad related PSR check.\nNOTE: The quirk should be used only on bipedal units that have an animal like appearance. PilotOptionsInfo.option.blood_stalker.displayableName=Blood Stalker (CamOps) PilotOptionsInfo.option.blood_stalker.description=Unit has -1 bonus against designated target, +2 penalty against all others; lasts until target retreats, can only be used once per battle. +PilotOptionsInfo.option.cross_country.displayableName=Cross-Country (CamOps) +PilotOptionsInfo.option.cross_country.description=Allows a unit to use terrain normally restricted to said unit at the cost of increased MP. PilotOptionsInfo.option.dodge_maneuver.displayableName= Dodge (MaxTech) PilotOptionsInfo.option.dodge_maneuver.description=Enables the unit to make a dodge maneuver instead of a physical attack.\nThis maneuver adds +2 to the BTH to physical attacks against the unit.\nNOTE: The dodge maneuver is declared during the weapons phase.\nNote: This ability is only used for BattleMeks. PilotOptionsInfo.option.eagle_eyes.displayableName= Eagle's Eyes (CamOps) diff --git a/megamek/src/megamek/common/Tank.java b/megamek/src/megamek/common/Tank.java index 9e570cd4558..77769ca330a 100644 --- a/megamek/src/megamek/common/Tank.java +++ b/megamek/src/megamek/common/Tank.java @@ -610,10 +610,18 @@ public boolean isLocationProhibited(Coords c, int currElevation) { boolean isAmphibious = hasWorkingMisc(MiscType.F_FULLY_AMPHIBIOUS); boolean hexHasRoad = hex.containsTerrain(Terrains.ROAD); boolean scoutBikeIntoLightWoods = (hex.terrainLevel(Terrains.WOODS) == 1) && hasQuirk(OptionsConstants.QUIRK_POS_SCOUT_BIKE); + boolean isCrossCountry = hasAbility(OptionsConstants.PILOT_CROSS_COUNTRY); // roads allow movement through hexes that you normally couldn't go through switch (movementMode) { case TRACKED: + if (isCrossCountry && !isSuperHeavy()) { + return ((hex.terrainLevel(Terrains.WATER) > 0) + && !hex.containsTerrain(Terrains.ICE) + && !hasFlotationHull && !isAmphibious) + || (hex.terrainLevel(Terrains.MAGMA) > 1); + } + if (!isSuperHeavy()) { return ((hex.terrainLevel(Terrains.WOODS) > 1) && !hexHasRoad) || ((hex.terrainLevel(Terrains.WATER) > 0) @@ -632,6 +640,15 @@ public boolean isLocationProhibited(Coords c, int currElevation) { || (hex.terrainLevel(Terrains.MAGMA) > 1); } case WHEELED: + if (isCrossCountry && !isSuperHeavy()) { + return ((hex.terrainLevel(Terrains.WATER) > 0) + && !hex.containsTerrain(Terrains.ICE) + && !hasFlotationHull && !isAmphibious) + || hex.containsTerrain(Terrains.MAGMA) + || ((hex.terrainLevel(Terrains.SNOW) > 1) && !hexHasRoad) + || (hex.terrainLevel(Terrains.GEYSER) == 2); + } + if (!isSuperHeavy()) { return (hex.containsTerrain(Terrains.WOODS) && !hexHasRoad && !scoutBikeIntoLightWoods) || (hex.containsTerrain(Terrains.ROUGH) && !hexHasRoad) @@ -655,6 +672,10 @@ public boolean isLocationProhibited(Coords c, int currElevation) { || (hex.terrainLevel(Terrains.GEYSER) == 2); } case HOVER: + if (isCrossCountry && !isSuperHeavy()) { + return (hex.terrainLevel(Terrains.MAGMA) > 1); + } + if (!isSuperHeavy()) { return (hex.containsTerrain(Terrains.WOODS) && !hexHasRoad && !scoutBikeIntoLightWoods) || (hex.containsTerrain(Terrains.JUNGLE) && !hexHasRoad) diff --git a/megamek/src/megamek/common/Terrain.java b/megamek/src/megamek/common/Terrain.java index dd278d848b9..0ab72533016 100644 --- a/megamek/src/megamek/common/Terrain.java +++ b/megamek/src/megamek/common/Terrain.java @@ -372,6 +372,8 @@ public void pilotingModifier(EntityMovementMode moveMode, PilotingRollData roll, public int movementCost(Entity e) { EntityMovementMode moveMode = e.getMovementMode(); int mp; + boolean isCrossCountry = e.hasAbility(OptionsConstants.PILOT_CROSS_COUNTRY); + switch (type) { case Terrains.MAGMA: return level - 1; @@ -381,17 +383,28 @@ public int movementCost(Entity e) { } return 0; case Terrains.RUBBLE: + boolean allowRubbleHoverTracked = ((moveMode == EntityMovementMode.HOVER) || (moveMode == EntityMovementMode.TRACKED)) && (level == 6); + if (level == 6) { mp = 2; } else { mp = 1; } + + if (isCrossCountry && e.isGround() && e.isCombatVehicle()) { + if (allowRubbleHoverTracked || (moveMode == EntityMovementMode.WHEELED)) { + mp *= 2; + } + } + if ((e instanceof Mech) && e.isSuperHeavy()) { mp -= 1; } + if (e.hasAbility(OptionsConstants.PILOT_TM_MOUNTAINEER)) { mp -= 1; } + if ((e.hasAbility(OptionsConstants.INFANTRY_FOOT_CAV) && (moveMode == EntityMovementMode.INF_LEG))) { mp -= 1; @@ -399,16 +412,26 @@ public int movementCost(Entity e) { return Math.max(0, mp); case Terrains.WOODS: mp = level; + if (isCrossCountry && e.isGround() && e.isCombatVehicle()) { + if (((level == 1) && ((moveMode == EntityMovementMode.HOVER) || (moveMode == EntityMovementMode.WHEELED))) + || (level > 1)) { + mp *= 2; + } + } + if ((e instanceof Mech) && e.isSuperHeavy()) { mp -= 1; } + if (e.hasAbility(OptionsConstants.PILOT_TM_FOREST_RANGER)) { mp -= 1; } + if ((e.hasAbility(OptionsConstants.INFANTRY_FOOT_CAV) && (moveMode == EntityMovementMode.INF_LEG))) { mp -= 1; } + if (e.hasAbility(OptionsConstants.PILOT_ANIMAL_MIMIC)) { if ((e.entityIsQuad()) || ((moveMode == EntityMovementMode.BIPED) && e.hasQuirk("animalistic"))) { mp -= 1; @@ -417,16 +440,23 @@ public int movementCost(Entity e) { return Math.max(0, mp); case Terrains.JUNGLE: mp = level +1; + if (isCrossCountry && e.isGround() && e.isCombatVehicle()) { + mp *= 2; + } + if ((e instanceof Mech) && e.isSuperHeavy()) { mp -= 1; } + if (e.hasAbility(OptionsConstants.PILOT_TM_FOREST_RANGER)) { mp -= 1; } + if ((e.hasAbility(OptionsConstants.INFANTRY_FOOT_CAV) && (moveMode == EntityMovementMode.INF_LEG))) { mp -= 1; } + if (e.hasAbility(OptionsConstants.PILOT_ANIMAL_MIMIC)) { if ((e.entityIsQuad()) || ((moveMode == EntityMovementMode.BIPED) && e.hasQuirk("animalistic"))) { mp -= 1; @@ -489,17 +519,28 @@ public int movementCost(Entity e) { } return Math.max(0, mp); case Terrains.ROUGH: + boolean allowRoughHoverTracked = ((moveMode == EntityMovementMode.HOVER) || (moveMode == EntityMovementMode.TRACKED)) && (level == 2); + if (level == 2) { mp = 2; } else { mp = 1; } + + if (isCrossCountry && e.isGround() && e.isCombatVehicle()) { + if ( allowRoughHoverTracked || (moveMode == EntityMovementMode.WHEELED)) { + mp *= 2; + } + } + if ((e instanceof Mech) && e.isSuperHeavy()) { mp -= 1; } + if (e.hasAbility(OptionsConstants.PILOT_TM_MOUNTAINEER)) { mp -= 1; } + if ((e.hasAbility(OptionsConstants.INFANTRY_FOOT_CAV) && (moveMode == EntityMovementMode.INF_LEG))) { mp -= 1; diff --git a/megamek/src/megamek/common/options/OptionsConstants.java b/megamek/src/megamek/common/options/OptionsConstants.java index 83152b3702b..db3acf2ffb1 100644 --- a/megamek/src/megamek/common/options/OptionsConstants.java +++ b/megamek/src/megamek/common/options/OptionsConstants.java @@ -143,7 +143,7 @@ public class OptionsConstants { public static final String PILOT_APTITUDE_GUNNERY = "aptitude_gunnery"; public static final String PILOT_APTITUDE_PILOTING = "aptitude_piloting"; public static final String PILOT_ANIMAL_MIMIC = "animal_mimic"; - // public static final String PILOT_CROSS_COUNTRY = "cross_country"; + public static final String PILOT_CROSS_COUNTRY = "cross_country"; public static final String PILOT_DODGE_MANEUVER = "dodge_maneuver"; // public static final String PILOT_DUST_OFF = "dust_off"; // public static final String PILOT_HVY_LIFTER = "hvy_lifter"; @@ -170,6 +170,7 @@ public class OptionsConstants { // public static final String PILOT_WIND_WALKER = "wind_walker"; public static final String PILOT_ZWEIHANDER = "zweihander"; + // GUNNERY SKILLS public static final String GUNNERY_BLOOD_STALKER = "blood_stalker"; public static final String GUNNERY_CLUSTER_HITTER = "cluster_hitter"; diff --git a/megamek/src/megamek/common/options/PilotOptions.java b/megamek/src/megamek/common/options/PilotOptions.java index 4d9ef71012c..49e20ad32fb 100755 --- a/megamek/src/megamek/common/options/PilotOptions.java +++ b/megamek/src/megamek/common/options/PilotOptions.java @@ -36,7 +36,7 @@ public void initialize() { IBasicOptionGroup adv = addGroup("adv", LVL3_ADVANTAGES); addOption(adv, OptionsConstants.PILOT_ANIMAL_MIMIC, false); - // addOption(adv, OptionsConstants.PILOT_CROSS_COUNTRY, false); + addOption(adv, OptionsConstants.PILOT_CROSS_COUNTRY, false); addOption(adv, OptionsConstants.PILOT_DODGE_MANEUVER, false); // addOption(adv, OptionsConstants.PILOT_DUST_OFF, false); // addOption(adv, OptionsConstants.PILOT_HVY_LIFTER, false);