public double getMassOfAllInBuilding(final IGame game, final Coords coords) { double mass = 0; // Add the mass of anyone else standing in/on this building. final IHex hex = game.getBoard().getHex(coords); final int buildingElevation = hex.terrainLevel(Terrains.BLDG_ELEV); final int bridgeElevation = hex.terrainLevel(Terrains.BRIDGE_ELEV); Iterator<Entity> crowd = game.getEntities(coords); while (crowd.hasNext()) { Entity e = crowd.next(); if (buildingElevation >= e.getElevation() || bridgeElevation >= e.getElevation()) { mass += e.getWeight(); } } return mass; }
private double calcBridgeHazard(Entity movingUnit, IHex hex, MoveStep step, boolean jumpLanding, IBoard board, StringBuilder logMsg) { logMsg.append("\n\tCalculating bridge hazard: "); // if we are going to BWONGGG into a bridge from below, then it's treated as a building. // Otherwise, bridge collapse checks have already been handled in validatePaths int bridgeElevation = hex.terrainLevel(Terrains.BRIDGE_ELEV); if ((bridgeElevation > step.getElevation()) && (bridgeElevation <= (step.getElevation() + movingUnit.getHeight()))) { return calcBuildingHazard(step, movingUnit, jumpLanding, board, logMsg); } return 0; }
/** * Modifier to attacks due to attacker terrain */ public static ToHitData getAttackerTerrainModifier(IGame game, int entityId) { final Entity attacker = game.getEntity(entityId); final IHex hex = game.getBoard().getHex(attacker.getPosition()); ToHitData toHit = new ToHitData(); // space screens; bonus depends on number (level) if (hex.terrainLevel(Terrains.SCREEN) > 0) { toHit.addModifier(hex.terrainLevel(Terrains.SCREEN) + 1, "attacker in screen(s)"); } return toHit; }
/** * Helper function that calculates the "utility" of placing a turret at the given coords * @param coords The location of the building being considered. * @return An "arbitrary" utility number */ private int calculateTurretDeploymentValue(final Coords coords) { // algorithm: a building is valued by the following formula: // (CF + height * 2) / # turrets placed on the roof // This way, we will generally favor unpopulated higher CF buildings, // but have some wiggle room in case of a really tall high CF building final Building building = game.getBoard().getBuildingAt(coords); final IHex hex = game.getBoard().getHex(coords); final int turretCount = 1 + game.getGunEmplacements(coords).size(); return (building.getCurrentCF(coords) + hex.terrainLevel(Terrains.BLDG_ELEV) * 2) / turretCount; }
/** * In hexes with buildings, returns the elevation relative to the roof. Otherwise returns the elevation * relative to the surface. */ public int getClearance() { IHex hex = entity.getGame().getBoard().getHex(getPosition()); if (hex.containsTerrain(Terrains.BLDG_ELEV)) { return elevation - hex.terrainLevel(Terrains.BLDG_ELEV); } return elevation; }
@Override public boolean isLocationProhibited(Coords c, int currElevation) { if (isAirborne()) { return false; } IHex hex = game.getBoard().getHex(c); // Additional restrictions for hidden units if (isHidden()) { // Can't deploy in paved hexes if (hex.containsTerrain(Terrains.PAVEMENT) || hex.containsTerrain(Terrains.ROAD)) { return true; } // Can't deploy on a bridge if ((hex.terrainLevel(Terrains.BRIDGE_ELEV) == currElevation) && hex.containsTerrain(Terrains.BRIDGE)) { return true; } // Can't deploy on the surface of water if (hex.containsTerrain(Terrains.WATER) && (currElevation == 0)) { return true; } } // grounded aeros have the same prohibitions as wheeled tanks return hex.containsTerrain(Terrains.WOODS) || hex.containsTerrain(Terrains.ROUGH) || ((hex.terrainLevel(Terrains.WATER) > 0) && !hex.containsTerrain(Terrains.ICE)) || hex.containsTerrain(Terrains.RUBBLE) || hex.containsTerrain(Terrains.MAGMA) || hex.containsTerrain(Terrains.JUNGLE) || (hex.terrainLevel(Terrains.SNOW) > 1) || (hex.terrainLevel(Terrains.GEYSER) == 2); }
/** * Returns this mech's jumping MP, modified for missing & underwater jets. */ @Override public int getJumpMPWithTerrain() { if (getPosition() == null) { return getJumpMP(); } int waterLevel = game.getBoard().getHex(getPosition()) .terrainLevel(Terrains.WATER); if ((waterLevel <= 0) || (getElevation() >= 0)) { return getJumpMP(); } return 0; }
/** * Checks if the entity is landing (from a jump) on ice-covered water. */ public PilotingRollData checkLandingOnIce( EntityMovementType overallMoveType, IHex curHex) { PilotingRollData roll = getBasePilotingRoll(overallMoveType); if (curHex.containsTerrain(Terrains.ICE) && (curHex.terrainLevel(Terrains.WATER) > 0)) { roll.append(new PilotingRollData(getId(), 0, "landing on ice-covered water")); addPilotingModifierForTerrain(roll); adjustDifficultTerrainPSRModifier(roll); } else { roll.addModifier(TargetRoll.CHECK_FALSE, "hex is not covered by ice"); } return roll; }
public PilotingRollData checkBogDown(MoveStep step, IHex curHex, Coords lastPos, Coords curPos, boolean isPavementStep) { PilotingRollData roll = new PilotingRollData(getId(), 4, "entering boggy terrain"); int bgMod = curHex.getBogDownModifier(getMovementMode(), false); final boolean onBridge = (curHex.terrainLevel(Terrains.BRIDGE) > 0) && (getElevation() == curHex.terrainLevel(Terrains.BRIDGE_ELEV)); if (!lastPos.equals(curPos) && (bgMod != TargetRoll.AUTOMATIC_SUCCESS) && (step.getMovementType(false) != EntityMovementType.MOVE_JUMP) && (getMovementMode() != EntityMovementMode.HOVER) && (getMovementMode() != EntityMovementMode.VTOL) && (getMovementMode() != EntityMovementMode.WIGE) && (step.getElevation() == 0) && !isPavementStep && !onBridge) { roll.append(new PilotingRollData(getId(), bgMod, "avoid bogging down")); } else { roll.addModifier(TargetRoll.CHECK_FALSE, "Check false: Not entering bog-down terrain, " + "or jumping/hovering over such terrain"); } return roll; }
/** * Checks if the entity is moving into depth 1+ water. If so, returns the * target roll for the piloting skill check. */ public PilotingRollData checkWaterMove(MoveStep step, EntityMovementType moveType, IHex curHex, Coords lastPos, Coords curPos, boolean isPavementStep) { if ((curHex.terrainLevel(Terrains.WATER) > 0) && (step.getElevation() < 0) && !lastPos.equals(curPos) && (moveType != EntityMovementType.MOVE_JUMP) && (getMovementMode() != EntityMovementMode.HOVER) && (getMovementMode() != EntityMovementMode.VTOL) && (getMovementMode() != EntityMovementMode.NAVAL) && (getMovementMode() != EntityMovementMode.HYDROFOIL) && (getMovementMode() != EntityMovementMode.SUBMARINE) && (getMovementMode() != EntityMovementMode.INF_UMU) && (getMovementMode() != EntityMovementMode.BIPED_SWIM) && (getMovementMode() != EntityMovementMode.QUAD_SWIM) && (getMovementMode() != EntityMovementMode.WIGE) && canFall() && !isPavementStep) { return checkWaterMove(curHex.terrainLevel(Terrains.WATER), moveType); } return checkWaterMove(0, moveType); }
@Override public boolean isAirborneVTOLorWIGE() { // stuff that moves like a VTOL is flying unless at elevation 0 or on // top of/in a building, if ((getMovementMode() == EntityMovementMode.VTOL) || (getMovementMode() == EntityMovementMode.WIGE)) { if ((game != null) && (game.getBoard() != null) && (getPosition() != null) && (game.getBoard().getHex(getPosition()) != null) && ((game.getBoard().getHex(getPosition()) .terrainLevel(Terrains.BLDG_ELEV) >= getElevation()) || (game .getBoard().getHex(getPosition()) .terrainLevel(Terrains.BRIDGE_ELEV) >= getElevation()))) { return false; } return getElevation() > 0; } return false; }
/** * Checks if the entity is moving into rubble. If so, returns the target * roll for the piloting skill check. */ public PilotingRollData checkRubbleMove(MoveStep step, EntityMovementType moveType, IHex curHex, Coords lastPos, Coords curPos, boolean isLastStep, boolean isPavementStep) { PilotingRollData roll = getBasePilotingRoll(moveType); boolean enteringRubble = true; addPilotingModifierForTerrain(roll, curPos, enteringRubble); if (!lastPos.equals(curPos) && ((moveType != EntityMovementType.MOVE_JUMP) || isLastStep) && (curHex.terrainLevel(Terrains.RUBBLE) > 0) && !isPavementStep && canFall()) { adjustDifficultTerrainPSRModifier(roll); if (hasAbility(OptionsConstants.PILOT_TM_MOUNTAINEER)) { roll.addModifier(-1, "Mountaineer"); } } else { roll.addModifier(TargetRoll.CHECK_FALSE, "Check false: Entity is not entering rubble"); } return roll; }
/** * Creates the Smoke Terrain Markers. * @param cloud */ public void createSmokeTerrain(SmokeCloud cloud){ for( Coords coords : cloud.getCoordsList() ){ IHex smokeHex = game.getBoard().getHex(coords); if (smokeHex != null ){ if (smokeHex.containsTerrain(Terrains.SMOKE)) { if (smokeHex.terrainLevel(Terrains.SMOKE) == SmokeCloud.SMOKE_LIGHT) { smokeHex.removeTerrain(Terrains.SMOKE); smokeHex.addTerrain(Terrains.getTerrainFactory() .createTerrain(Terrains.SMOKE, SmokeCloud.SMOKE_HEAVY)); server.getHexUpdateSet().add(coords); } } else if (cloud.getSmokeLevel() > SmokeCloud.SMOKE_NONE) { smokeHex.addTerrain(Terrains.getTerrainFactory() .createTerrain(Terrains.SMOKE, cloud.getSmokeLevel())); server.getHexUpdateSet().add(coords); } } } }
/** * Burning woods, with chance to be burnt down already */ protected static void postProcessForestFire(IHex[] hexSet, int modifier) { int n; IHex field; int level, newlevel; int severity; ITerrainFactory f = Terrains.getTerrainFactory(); for (n = 0; n < hexSet.length; n++) { field = hexSet[n]; level = field.terrainLevel(Terrains.WOODS); if (level != ITerrain.LEVEL_NONE) { severity = Compute.randomInt(5) - 2 + modifier; newlevel = level - severity; if (newlevel <= level) { field.removeTerrain(Terrains.WOODS); if (newlevel <= 0) { field.addTerrain(f.createTerrain(Terrains.ROUGH, 1)); } else { field.addTerrain(f.createTerrain(Terrains.WOODS, newlevel)); field.addTerrain(f.createTerrain(Terrains.FIRE, 1)); } } } } }
/** * get final elevation relative to the tops of any buildings in the hex * @return */ public int getFinalClearance() { if (getLastStep() != null) { return getLastStep().getClearance(); } IHex hex = entity.getGame().getBoard().getHex(getEntity().getPosition()); if (hex.containsTerrain(Terrains.BLDG_ELEV)) { return getEntity().getElevation() - hex.terrainLevel(Terrains.BLDG_ELEV); } return getEntity().getElevation(); }
/** * Modifier to physical attack BTH due to pilot advantages */ public static void modifyPhysicalBTHForAdvantages(Entity attacker, Entity target, ToHitData toHit, IGame game) { if (attacker.hasAbility(OptionsConstants.PILOT_MELEE_SPECIALIST) && (attacker instanceof Mech)) { toHit.addModifier(-1, OptionsConstants.PILOT_MELEE_SPECIALIST); } IHex curHex = game.getBoard().getHex(attacker.getPosition()); if (attacker.hasAbility(OptionsConstants.PILOT_TM_FROGMAN) && ((attacker instanceof Mech) || (attacker instanceof Protomech)) && (curHex.terrainLevel(Terrains.WATER) > 1)) { toHit.addModifier(-1, "Frogman"); } if (attacker.hasAbility(OptionsConstants.UNOFF_CLAN_PILOT_TRAINING)) { toHit.addModifier(1, "clan pilot training"); } // Mek targets that are dodging are harder to hit. if ((target != null) && (target instanceof Mech) && target.hasAbility(OptionsConstants.PILOT_DODGE_MANEUVER) && (target.dodging)) { toHit.addModifier(2, "target is dodging"); } }
/** * Returns this mech's jumping MP, modified for missing & underwater jets * and gravity. */ @Override public int getJumpMPWithTerrain() { if ((getPosition() == null) || (game.getBoard().getHex(getPosition()) == null) || (getJumpType() == JUMP_BOOSTER)) { return getJumpMP(); } int waterLevel = 0; if (!isOffBoard()) { waterLevel = game.getBoard().getHex(getPosition()) .terrainLevel(Terrains.WATER); } if ((waterLevel <= 0) || (getElevation() >= 0)) { return getJumpMP(); } else if (waterLevel > 1) { return 0; } else { // waterLevel == 1 return applyGravityEffectsOnMP(torsoJumpJets()); } }
@Override public PilotingRollData addEntityBonuses(PilotingRollData prd) { if (motivePenalty > 0) { prd.addModifier(motivePenalty, "Steering Damage"); } if (commanderHit) { prd.addModifier(1, "commander injured"); } if (driverHit) { prd.addModifier(2, "driver injured"); } // are we wheeled and in light snow? IHex hex = game.getBoard().getHex(getPosition()); if ((null != hex) && (getMovementMode() == EntityMovementMode.WHEELED) && (hex.terrainLevel(Terrains.SNOW) == 1)) { prd.addModifier(1, "thin snow"); } // VDNI bonus? if (hasAbility(OptionsConstants.MD_VDNI) && !hasAbility(OptionsConstants.MD_BVDNI)) { prd.addModifier(-1, "VDNI"); } if (hasModularArmor()) { prd.addModifier(1, "Modular Armor"); } return prd; }
@Override public boolean handle(IGame.Phase phase, Vector<Report> vPhaseReport) { if (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_START_FIRE) && (game.getPlanetaryConditions().getAtmosphere() >= PlanetaryConditions.ATMO_TRACE)) { int rear = (ae.getFacing() + 3 + (weapon.isMechTurretMounted() ? weapon .getFacing() : 0)) % 6; Coords src = ae.getPosition(); Coords rearCoords = src.translated(rear); IBoard board = game.getBoard(); IHex currentHex = board.getHex(src); if (!board.contains(rearCoords)) { rearCoords = src; } else if (board.getHex(rearCoords).getLevel() > currentHex .getLevel()) { rearCoords = src; } else if ((board.getBuildingAt(rearCoords) != null) && ((board.getHex(rearCoords).terrainLevel( Terrains.BLDG_ELEV) + board.getHex(rearCoords) .getLevel()) > currentHex.getLevel())) { rearCoords = src; } server.createSmoke(rearCoords, SmokeCloud.SMOKE_HEAVY, 2); } return super.handle(phase, vPhaseReport); }
@Override public boolean handle(IGame.Phase phase, Vector<Report> vPhaseReport) { if (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_START_FIRE) && (game.getPlanetaryConditions().getAtmosphere() >= PlanetaryConditions.ATMO_TRACE)) { int rear = (ae.getFacing() + 3 + (weapon.isMechTurretMounted() ? weapon .getFacing() : 0)) % 6; Coords src = ae.getPosition(); Coords rearCoords = src.translated(rear); IBoard board = game.getBoard(); IHex currentHex = board.getHex(src); if (!board.contains(rearCoords)) { rearCoords = src; } else if (board.getHex(rearCoords).getLevel() > currentHex .getLevel() + 4) { rearCoords = src; } else if ((board.getBuildingAt(rearCoords) != null) && (board.getHex(rearCoords).terrainLevel( Terrains.BLDG_ELEV) + board.getHex(rearCoords).getLevel() > currentHex .getLevel() + 4)) { rearCoords = src; } server.createSmoke(rearCoords, SmokeCloud.SMOKE_HEAVY, 2); } return super.handle(phase, vPhaseReport); }