return; // not on board.
}
int flakElevation = altitude - hex.surface();
Report r;
if (!flak) {
vPhaseReport.addAll(tryClearHex(coords, damage * 2, subjectId));
}
Building bldg = game.getBoard().getBuildingAt(coords);
int bldgAbsorbs = 0;
if ((bldg != null) && !(flak && (flakElevation > hex.terrainLevel(Terrains.BLDG_ELEV)))) {
bldgAbsorbs = bldg.getPhaseCF(coords) / 10;
if (!((ammo != null) && (ammo.getMunitionType() == AmmoType.M_FLECHETTE))) {
// damage the building
Vector<Report> buildingReport = damageBuilding(bldg, damage, coords);
for (Report report : buildingReport) {
report.subject = subjectId;
}
vPhaseReport.addAll(buildingReport);
addNewLines();
}
}
if (flak && ((flakElevation <= 0) || (flakElevation <= hex.terrainLevel(Terrains.BLDG_ELEV)) || (flakElevation == hex.terrainLevel(Terrains.BRIDGE_ELEV)))) {
// Flak in this hex would only hit landed units
return;
}
// get units in hex
for (Enumeration<Entity> impactHexHits = game.getEntities(coords); impactHexHits.hasMoreElements();) {
Entity entity = impactHexHits.nextElement();
int hits = damage;
ToHitData toHit = new ToHitData();
int cluster = 5;
// Check: is entity excluded?
if (entity == exclude) {
continue;
}
// Check: is entity inside building?
if ((bldg != null) && (bldgAbsorbs > 0) && (entity.getElevation() < hex.terrainLevel(Terrains.BLDG_ELEV))) {
cluster -= bldgAbsorbs;
if (entity instanceof Infantry) {
continue; // took its damage already from building damage
} else if (cluster <= 0) {
// entity takes no damage
r = new Report(6426);
r.subject = subjectId;
r.addDesc(entity);
vPhaseReport.add(r);
continue;
} else {
r = new Report(6425);
r.subject = subjectId;
r.add(bldgAbsorbs);
vPhaseReport.add(r);
}
}
if (flak) {
// Check: is entity not a VTOL in flight
if (!((entity instanceof VTOL) || (entity.getMovementMode() == IEntityMovementMode.VTOL))) {
continue;
}
// Check: is entity at correct elevation?
if (entity.getElevation() != flakElevation) {
continue;
}
} else {
// Check: is entity a VTOL in flight?
if ((entity instanceof VTOL) || (entity.getMovementMode() == IEntityMovementMode.VTOL)) {
// VTOLs take no damage from normal artillery unless landed
if ((entity.getElevation() != 0) && (entity.getElevation() != hex.terrainLevel(Terrains.BLDG_ELEV)) && (entity.getElevation() != hex.terrainLevel(Terrains.BRIDGE_ELEV))) {
continue;
}
}
}
// Work out hit table to use
if (attackSource != null) {
toHit.setSideTable(entity.sideTable(attackSource));
if ((ammo != null) && (ammo.getMunitionType() == AmmoType.M_CLUSTER) && attackSource.equals(coords)) {
if (entity instanceof Mech) {
toHit.setHitTable(ToHitData.HIT_ABOVE);
} else if (entity instanceof Tank) {
toHit.setSideTable(ToHitData.SIDE_FRONT);
toHit.addModifier(2, "cluster artillery hitting a Tank");
}
}
}
// convention infantry take x2 damage from AE weapons
if ((entity instanceof Infantry) && !(entity instanceof BattleArmor)) {
hits *= 2;
}
// Entity/ammo specific damage modifiers
if (ammo != null) {
if (ammo.getMunitionType() == AmmoType.M_CLUSTER) {
if (hex.containsTerrain(Terrains.FORTIFIED) && (entity instanceof Infantry) && !(entity instanceof BattleArmor)) {
hits *= 2;
}
} else if (ammo.getMunitionType() == AmmoType.M_FLECHETTE) {
// wheeled and hover tanks take movement critical
if ((entity instanceof Tank) && ((entity.getMovementMode() == IEntityMovementMode.WHEELED) || (entity.getMovementMode() == IEntityMovementMode.HOVER))) {
r = new Report(6480);
r.subject = entity.getId();
r.addDesc(entity);
r.add(toHit.getTableDesc());
r.add(0);
vPhaseReport.add(r);
vPhaseReport.addAll(vehicleMotiveDamage((Tank) entity, 0));
continue;
}
// only infantry and support vees with bar < 5 are affected
if ((entity instanceof BattleArmor) || (entity.getBARRating() > 4)) {
continue;
}
if (entity instanceof Infantry) {
hits = Compute.d6(damage);
hits *= 2;
}
if (entity.getBARRating() < 5) {
switch (ammo.getAmmoType()) {
case AmmoType.T_LONG_TOM:
// hack: check if damage is still at 4, so we're in the
// center hex. otherwise, do no damage
if (damage == 4) {
damage = (5 - entity.getBARRating()) * 5;
} else {
continue;
}
break;
case AmmoType.T_SNIPER:
// hack: check if damage is still at 2, so we're in the
// center hex. otherwise, do no damage
if (damage == 2) {
damage = (5 - entity.getBARRating()) * 3;
} else {
continue;
}
break;
case AmmoType.T_THUMPER:
// no need to check for damage, because falloff = damage for the thumper
damage = 5 - entity.getBARRating();
break;
}
}
}
}
// Do the damage
r = new Report(6480);
r.subject = entity.getId();
r.addDesc(entity);
r.add(toHit.getTableDesc());
r.add(hits);
vPhaseReport.add(r);
if (entity instanceof BattleArmor) {
// BA take full damage to each trooper, ouch!
for (int loc = 0; loc < entity.locations(); loc++) {
if (entity.getInternal(loc) > 0) {