if ( !bAllShotsHit ) {
if ( bAllShotsHit ) {
    private void resolveWeaponAttack(WeaponResult wr, int lastEntityId) {        final Entity ae = game.getEntity(wr.waa.getEntityId());        final Targetable target = game.getTarget(wr.waa.getTargetType(), wr.waa.getTargetId());        Entity entityTarget = null;        if (target.getTargetType() == Targetable.TYPE_ENTITY) {            entityTarget = (Entity)target;        }        final Mounted weapon = ae.getEquipment(wr.waa.getWeaponId());        final WeaponType wtype = (WeaponType)weapon.getType();        final boolean isWeaponInfantry = wtype.hasFlag(WeaponType.F_INFANTRY);        // 2002-09-16 Infantry weapons have unlimited ammo.        final boolean usesAmmo = wtype.getAmmoType() != AmmoType.T_NA &&            wtype.getAmmoType() != AmmoType.T_BA_MG &&            wtype.getAmmoType() != AmmoType.T_BA_SMALL_LASER &&            !isWeaponInfantry;        final Mounted ammo = usesAmmo ? weapon.getLinked() : null;        final AmmoType atype = ammo == null ? null : (AmmoType)ammo.getType();        Infantry platoon = null;        final boolean isBattleArmorAttack = wtype.hasFlag(WeaponType.F_BATTLEARMOR);        ToHitData toHit = wr.toHit;        boolean bInferno = (usesAmmo && atype.getMunitionType() == AmmoType.M_INFERNO);        if (!bInferno) {            // also check for inferno infantry            bInferno = (isWeaponInfantry && wtype.hasFlag(WeaponType.F_INFERNO));        }        final boolean targetInBuilding =             Compute.isInBuilding( game, entityTarget );        // Which building takes the damage?        Building bldg = game.board.getBuildingAt( target.getPosition() );                if (lastEntityId != ae.getId()) {            phaseReport.append("\nWeapons fire for " ).append( ae.getDisplayName() ).append( "\n");        }        // Swarming infantry can stop during any weapons phase after start.        if ( Infantry.STOP_SWARM.equals( wtype.getInternalName() ) ) {            // ... but only as their *only* attack action.            if ( toHit.getValue() == ToHitData.IMPOSSIBLE ) {                phaseReport.append( "Swarm attack can not be ended (" +                                    toHit.getDesc() ).append( ")\n" );                return;            } else {                phaseReport.append( "Swarm attack ended.\n" );                // Only apply the "stop swarm 'attack'" to the swarmed Mek.                if ( ae.getSwarmTargetId() != target.getTargetId() ) {                    Entity other = game.getEntity( ae.getSwarmTargetId() );                    other.setSwarmAttackerId( Entity.NONE );                } else {                    entityTarget.setSwarmAttackerId( Entity.NONE );                }                ae.setSwarmTargetId( Entity.NONE );                return;            }        }        // Report weapon attack and its to-hit value.        phaseReport.append("    " ).append( wtype.getName() ).append( " at " ).append( target.getDisplayName());        if (toHit.getValue() == ToHitData.IMPOSSIBLE) {            phaseReport.append(", but the shot is impossible (" ).append( toHit.getDesc() ).append( ")\n");            return;        } else if (toHit.getValue() == ToHitData.AUTOMATIC_FAIL) {            phaseReport.append(", the shot is an automatic miss (" ).append( toHit.getDesc() ).append( "), ");        } else if (toHit.getValue() == ToHitData.AUTOMATIC_SUCCESS) {            phaseReport.append(", the shot is an automatic hit (" ).append( toHit.getDesc() ).append( "), ");        } else {            phaseReport.append("; needs " ).append( toHit.getValue() ).append( ", ");        }                // if firing an HGR unbraced, schedule a PSR        if (wtype.getAmmoType() == AmmoType.T_GAUSS_HEAVY && ae.mpUsed > 0) {            // the mod is weight-based            int nMod;            if (ae.getWeight() <= Mech.WEIGHT_LIGHT) {                nMod = 2;            } else if (ae.getWeight() <= Mech.WEIGHT_MEDIUM) {                nMod = 1;            } else if (ae.getWeight() <= Mech.WEIGHT_HEAVY) {                nMod = 0;            } else {                nMod = -1;            }            PilotingRollData psr = new PilotingRollData(ae.getId(), nMod, "fired HeavyGauss unbraced");            psr.setCumulative(false); // about the only time we set this flag            game.addPSR(psr);        }                // dice have been rolled, thanks        phaseReport.append("rolls " ).append( wr.roll ).append( " : ");                // check for AC jams        int nShots = weapon.howManyShots();        if (nShots > 1) {            int jamCheck = 0;            if (wtype.getAmmoType() == AmmoType.T_AC_ULTRA && weapon.curMode().equals("Ultra")) {                jamCheck = 2;            } else if (wtype.getAmmoType() == AmmoType.T_AC_ROTARY) {                if (nShots == 2) {                    jamCheck = 2;                }                else if (nShots == 4) {                    jamCheck = 3;                }                else if (nShots == 6) {                    jamCheck = 4;                }            }                    if (jamCheck > 0 && wr.roll <= jamCheck) {                phaseReport.append("misses AND THE AUTOCANNON JAMS.\n");                weapon.setJammed(true);                // ultras are destroyed by jamming                if (wtype.getAmmoType() == AmmoType.T_AC_ULTRA) {                    weapon.setHit(true);                }                return;            }        }                // do we hit?        boolean bMissed = false;        if (wr.roll < toHit.getValue()) {            // miss            bMissed = true;            phaseReport.append("misses.\n");            if (wr.amsShotDown > 0) {                phaseReport.append("\tAMS activates, firing " ).append( wr.amsShotDown ).append( " shot(s).\n");            }                        // Non-streaks can set fires on misses            // Buildings can't be accidentally ignited.            if ( bldg != null &&                 entityTarget != null &&                 toHit.getValue() != TargetRoll.AUTOMATIC_FAIL &&                 wtype.getAmmoType() != AmmoType.T_SRM_STREAK ) {                                // make sure it's a fire-setting weapon                if (bInferno || wtype.getFireTN() != TargetRoll.IMPOSSIBLE) {                    tryIgniteHex(target.getPosition(), bInferno, 11);                }            }            // BMRr, pg. 51: "All shots that were aimed at a target inside            // a building and miss do full damage to the building instead."            if ( !targetInBuilding ) {                return;            }        }                // special case NARC hits.  No damage, but a beacon is appended        if (!bMissed && wtype.getAmmoType() == AmmoType.T_NARC) {            // TODO: AMS can shoot down NARC pods too.            if (entityTarget == null) {                phaseReport.append("hits, but doesn't do anything.\n");            } else {                entityTarget.setNarcedBy(ae.getOwner().getTeam());                phaseReport.append("hits.  Pod attached.\n");            }            return;        }        // yeech.  handle damage. . different weapons do this in very different ways        int hits = 1, nCluster = 1, nSalvoBonus = 0;        int nDamPerHit = wtype.getDamage();        boolean bSalvo = false;        // ecm check is heavy, so only do it once        boolean bCheckedECM = false;        boolean bECMAffected = false;        boolean bMekStealthActive = false;        String sSalvoType = " shot(s) ";        boolean bAllShotsHit = false;        // All shots fired by a Streak SRM weapon, during        // a Mech Swarm hit, or at an adjacent building.        if ( wtype.getAmmoType() == AmmoType.T_SRM_STREAK ||             ae.getSwarmTargetId() == wr.waa.getTargetId() ||             ( ( target.getTargetType() == Targetable.TYPE_BLDG_IGNITE ||                 target.getTargetType() == Targetable.TYPE_BUILDING ) &&               ae.getPosition().distance( target.getPosition() ) <= 1 ) ) {            bAllShotsHit = true;        }        // Mek swarms attach the attacker to the target.        if ( !bMissed && Infantry.SWARM_MEK.equals( wtype.getInternalName() ) ) {            // Is the target already swarmed?            if ( Entity.NONE != entityTarget.getSwarmAttackerId() ) {                phaseReport.append( "succeds, but the defender is " );                phaseReport.append( "already swarmed by another unit.\n" );            } else {                phaseReport.append( "succeeds!  Defender swarmed.\n" );                ae.setSwarmTargetId( wr.waa.getTargetId() );                entityTarget.setSwarmAttackerId( wr.waa.getEntityId() );            }            return;        }        // Magnetic Mine Launchers roll number of hits on battle armor        // hits table but use # mines firing instead of men shooting.        else if ( wtype.getInternalName().equals(BattleArmor.MINE_LAUNCHER) ) {            hits = nShots;            if ( !bAllShotsHit ) {                hits = Compute.getBattleArmorHits( hits );            }            bSalvo = true;            sSalvoType = " mine(s) ";        }        // Other battle armor attacks use # of men firing to determine hits.        // Each hit can be in a new location. The damage per shot comes from        // the "racksize".        else if ( isBattleArmorAttack ) {            bSalvo = true;            platoon = (Infantry) ae;            nCluster = 1;            nDamPerHit = wtype.getRackSize();            hits = platoon.getShootingStrength();            // All attacks during Mek Swarms hit; all            // others use the Battle Armor hits table.            if ( !bAllShotsHit ) {                hits = Compute.getBattleArmorHits( hits );            }            // Handle Inferno SRM squads.            if (bInferno) {                nCluster = hits;                nDamPerHit = 0;                sSalvoType = " Inferno missle(s) ";                bSalvo = false;            }        }        // Infantry damage depends on # men left in platoon.        else if (isWeaponInfantry) {            bSalvo = true;            platoon = (Infantry)ae;            nCluster = 5;            nDamPerHit = 1;            hits = platoon.getDamage(platoon.getShootingStrength());            // Handle Inferno SRM infantry.            if (bInferno) {                nCluster = hits;                nDamPerHit = 0;                sSalvoType = " Inferno missle(s) ";                bSalvo = false;            }        } else if (wtype.getDamage() == WeaponType.DAMAGE_MISSILE ||                   wtype.hasFlag(WeaponType.F_MISSILE_HITS) ) {            bSalvo = true;            // Weapons with ammo type T_BA_MG or T_BA_SMALL_LASER            // don't have an atype object.            if ( wtype.getAmmoType() == AmmoType.T_BA_MG ||                 wtype.getAmmoType() == AmmoType.T_BA_SMALL_LASER ) {                nDamPerHit = Math.abs( wtype.getAmmoType() );            } else {                sSalvoType = " missile(s) ";                nDamPerHit = atype.getDamagePerShot();            }                        if ( wtype.getAmmoType() == AmmoType.T_LRM ||                 wtype.getAmmoType() == AmmoType.T_MRM ||                  wtype.getAmmoType() == AmmoType.T_ATM ) {                nCluster = 5;            }            // calculate # of missiles hitting            if ( wtype.getAmmoType() == AmmoType.T_LRM ||                 wtype.getAmmoType() == AmmoType.T_SRM ||                  wtype.getAmmoType() == AmmoType.T_ATM ) {                                // check for artemis, else check for narc                Mounted mLinker = weapon.getLinkedBy();                if ( wtype.getAmmoType() == AmmoType.T_ATM ||                     ( mLinker != null &&                       mLinker.getType() instanceof MiscType &&                        !mLinker.isDestroyed() && !mLinker.isMissing() &&                       mLinker.getType().hasFlag(MiscType.F_ARTEMIS) ) ) {                                                // check ECM interference                    if (!bCheckedECM) {                        // Attacking Meks using stealth suffer ECM effects.                        if ( ae instanceof Mech ) {                            bMekStealthActive = ae.isStealthActive();                        } else {                            bECMAffected = Compute.isAffectedByECM(ae, ae.getPosition(), target.getPosition());                        }                        bCheckedECM = true;                    }                    if (!bECMAffected && !bMekStealthActive) {                        nSalvoBonus += 2;                    }                } else if (entityTarget != null && entityTarget.isNarcedBy(ae.getOwner().getTeam())) {                    // check ECM interference                    if (!bCheckedECM) {                        // Attacking Meks using stealth suffer ECM effects.                        if ( ae instanceof Mech ) {                            bMekStealthActive = ae.isStealthActive();                        } else {                            bECMAffected = Compute.isAffectedByECM(ae, ae.getPosition(), target.getPosition());                        }                        bCheckedECM = true;                    }                    if (!bECMAffected && !bMekStealthActive) {                        nSalvoBonus += 2;                    }                }            }            // If dealing with Inferno rounds set damage to zero and reset            // all salvo bonuses (cannot mix with other special munitions).            if (bInferno) {                    nDamPerHit = 0;                    nSalvoBonus = 0;                    sSalvoType = " inferno missile(s) ";                    bSalvo = false;            }            // Large MRM missile racks roll twice.            // MRM missiles never recieve hit bonuses.            if ( wtype.getRackSize() == 30 || wtype.getRackSize() == 40 ) {                hits = Compute.missilesHit(wtype.getRackSize() / 2) +                    Compute.missilesHit(wtype.getRackSize() / 2);            }            // Battle Armor units multiply their racksize by the number            // of men shooting and they can't get missile hit bonuses.            else if ( ae instanceof BattleArmor ) {                platoon = (Infantry) ae;                int temp = wtype.getRackSize() * platoon.getShootingStrength();                // Do all shots hit?                if ( !bAllShotsHit ) {                    hits = temp;                } else {                    // Account for more than 20 missles hitting.                    hits = 0;                    while ( temp > 20 ) {                        hits += Compute.missilesHit( 20 );                        temp -= 20;                    }                    hits += Compute.missilesHit( temp );                } // End not-all-shots-hit            }            // If all shots hit, use the full racksize.            else if ( bAllShotsHit ) {                hits = wtype.getRackSize();            }            // In all other circumstances, roll for hits.            else {                hits = Compute.missilesHit(wtype.getRackSize(), nSalvoBonus);            }            // Advanced SRM's only hit with even numbers of missles.            if ( null != atype &&                 atype.getAmmoType() == AmmoType.T_SRM_ADVANCED ) {                hits = 2 * (int) Math.floor( (1.0 + (float) hits) / 2.0);            }        } else if (atype != null && atype.getMunitionType() == AmmoType.M_CLUSTER) {            // Cluster shots break into single point clusters.            bSalvo = true;            hits = wtype.getRackSize();            if ( !bAllShotsHit ) {                hits = Compute.missilesHit( hits );            }            nDamPerHit = 1;        } else if (nShots > 1) {            // this should handle multiple attacks from ultra and rotary ACs            bSalvo = true;            hits = nShots;            if ( !bAllShotsHit ) {                hits = Compute.missilesHit( hits );            }        }        else if (wtype.getAmmoType() == AmmoType.T_GAUSS_HEAVY) {            // HGR does range-dependent damage            int nRange = ae.getPosition().distance(target.getPosition());            if (nRange <= wtype.getShortRange()) {                nDamPerHit = 25;            } else if (nRange <= wtype.getMediumRange()) {                nDamPerHit = 20;            } else {                nDamPerHit = 10;            }        }        // Some weapons double the number of hits scored.        if ( wtype.hasFlag(WeaponType.F_DOUBLE_HITS) ) {            hits *= 2;        }        // We've calculated how many hits.  At this point, any missed         // shots damage the building instead of the target.        if ( bMissed ) {            if ( targetInBuilding && bldg != null ) {                // Reduce the number of hits by AMS hits.                if (wr.amsShotDown > 0) {                    int shotDown = Math.min(wr.amsShotDown, hits);                    phaseReport.append("\tAMS shoots down ")                        .append(shotDown).append(" missile(s).\n");                    hits -= wr.amsShotDown;                }                // Is the building hit by Inferno rounds?                if ( bInferno && hits > 0 ) {                                    // start a fire in the targets hex                    Coords c = target.getPosition();                    Hex h = game.getBoard().getHex(c);                                    // Is there a fire in the hex already?                    if ( h.contains( Terrain.FIRE ) ) {                        phaseReport.append( "        " )                            .append( hits )                            .append( " Inferno rounds added to hex " )                            .append( c.getBoardNum() )                            .append( ".\n" );                    } else {                        phaseReport.append( "        " )                            .append( hits )                            .append( " Inferno rounds start fire in hex " )                            .append( c.getBoardNum() )                            .append( ".\n" );                        h.addTerrain(new Terrain(Terrain.FIRE, 1));                    }                    game.board.addInfernoTo                        ( c, InfernoTracker.STANDARD_ROUND, hits );                    sendChangedHex(c);                                }                                // Damage the building in one big lump.                else {                    // Only report if damage was done to the building.                    int toBldg = hits * nDamPerHit;                    if ( toBldg > 0 ) {                        phaseReport.append( "        " )                            .append( damageBuilding( bldg, toBldg ) )                            .append( "\n" );                    }                } // End rounds-hit            } // End missed-target-in-building            return;        } // End missed-target        // The building shields all units from a certain amount of damage.        // The amount is based upon the building's CF at the phase's start.        int bldgAbsorbs = 0;        if ( targetInBuilding && bldg != null ) {            bldgAbsorbs = (int) Math.ceil( bldg.getPhaseCF() / 10.0 );        }        // All attacks (except from infantry weapons)        // during Mek Swarms hit the same location.        if ( !isWeaponInfantry &&             ae.getSwarmTargetId() == wr.waa.getTargetId() ) {            nCluster = hits;        }        // Battle Armor MGs do one die of damage per hit to PBI.        if ( wtype.getAmmoType() == AmmoType.T_BA_MG &&             (target instanceof Infantry) &&             !(target instanceof BattleArmor) ) {            // ASSUMPTION: Building walls protect infantry from BA MGs.            if ( bldgAbsorbs > 0 ) {                int toBldg = nDamPerHit * hits;                phaseReport.append( hits )                    .append( sSalvoType )                    .append( "hit,\n        but " )                    .append( damageBuilding( bldg,                               Math.min( toBldg, bldgAbsorbs ),                               " absorbs the shots, taking " ) )                    .append( "\n" );                return;            }            nDamPerHit = Compute.d6(hits);            phaseReport.append( "riddles the target with " ).append(                 nDamPerHit ).append( sSalvoType ).append( "and " );            hits = 1;        }        // Mech and Vehicle MGs do *DICE* of damage to PBI.        else if (atype != null && atype.hasFlag(AmmoType.F_MG) &&                  !isWeaponInfantry && (target instanceof Infantry) &&                  !(target instanceof BattleArmor) ) {            int dice = wtype.getDamage();            // A building may absorb the entire shot.            if ( nDamPerHit <= bldgAbsorbs ) {                int toBldg = nDamPerHit * hits;                int curCF = bldg.getCurrentCF();                curCF = Math.min( curCF, toBldg );                bldg.setCurrentCF( curCF );                if ( bSalvo ) {                    phaseReport.append( hits )                        .append( sSalvoType )                        .append( "hit,\n" );                } else{                    phaseReport.append( "hits,\n" );                }                phaseReport.append( "        but " )                    .append( damageBuilding( bldg,                               Math.min( toBldg, bldgAbsorbs ),                               " absorbs the shots, taking " ) )                    .append( "\n" );                return;            }            // If a building absorbs partial damage, reduce the dice of damage.            else if ( bldgAbsorbs > 0 ) {                dice -= bldgAbsorbs;            }            nDamPerHit = Compute.d6( dice );            phaseReport.append( "riddles the target with " ).append(                 nDamPerHit ).append( sSalvoType ).append( ".\n" );            bSalvo = true;            // If a building absorbed partial damage, report it now            // instead of later and then clear the variable.            if ( bldgAbsorbs > 0 ) {                phaseReport.append( "        " )                    .append( damageBuilding( bldg, bldgAbsorbs ) );                bldgAbsorbs = 0;            }        }        // Report the number of hits.  Infernos have their own reporting        else if (bSalvo && !bInferno) {            phaseReport.append( hits ).append( sSalvoType ).append( "hit" )                .append( toHit.getTableDesc() );            if (bECMAffected) {                phaseReport.append(" (ECM prevents bonus)");            }            else if (bMekStealthActive) {                phaseReport.append(" (active Stealth prevents bonus)");            }            if (nSalvoBonus > 0) {                phaseReport.append(" (w/ +")                    .append(nSalvoBonus)                    .append(" bonus)");            }            phaseReport.append(".");                        if (wr.amsShotDown > 0) {                int shotDown = Math.min(wr.amsShotDown, hits);                phaseReport.append("\n\tAMS engages, firing ")                    .append(wr.amsShotDown).append(" shots, shooting down ")                    .append(shotDown).append(" missile(s).");                hits -= wr.amsShotDown;            }        }        // convert the ATM missile damages to LRM type 5 point cluster damage        // done here after AMS has been performed        if (wtype.getAmmoType() == AmmoType.T_ATM)        {            hits = nDamPerHit * hits;            nDamPerHit = 1;        }        // Make sure the player knows when his attack causes no damage.        if ( hits == 0 ) {            phaseReport.append( "attack deals zero damage.\n" );        }        // for each cluster of hits, do a chunk of damage        while (hits > 0) {            int nDamage;            // If the attack was with inferno rounds then            // do heat and fire instead of damage.            if ( bInferno ) {                // AMS can shoot down infernos, too.                if (wr.amsShotDown > 0) {                    int shotDown = Math.min(wr.amsShotDown, hits);                    phaseReport.append("\n\tAMS engages, firing ")                        .append(wr.amsShotDown).append(" shots, shooting down ")                        .append(shotDown).append(" missile(s).");                    hits -= wr.amsShotDown;                    if ( hits <= 0 ) {                        continue;                    }                }                // targeting a hex for ignition                if( target.getTargetType() == Targetable.TYPE_HEX_IGNITE ||                    target.getTargetType() == Targetable.TYPE_BLDG_IGNITE ) {                    phaseReport.append( "hits with " )                        .append( hits )                        .append( " inferno missles.\n" );                    // Unless there a fire in the hex already, start one.                    Coords c = target.getPosition();                    Hex h = game.getBoard().getHex(c);                    if ( !h.contains( Terrain.FIRE ) ) {                        phaseReport.append( " Fire started in hex " )                            .append( c.getBoardNum() )                            .append( ".\n" );                        h.addTerrain(new Terrain(Terrain.FIRE, 1));                    }                    game.board.addInfernoTo                        ( c, InfernoTracker.STANDARD_ROUND, hits );                    sendChangedHex(c);                    return;                }                                // Targeting an entity                if (entityTarget != null ) {                    entityTarget.infernos.add( InfernoTracker.STANDARD_ROUND,                                               hits );                    phaseReport.append( "hits with " )                        .append( hits )                        .append( " inferno missles." );                    phaseReport.append("\n        " )                        .append( target.getDisplayName() )                        .append( " now on fire for ")                        .append( entityTarget.infernos.getTurnsLeftToBurn() )                        .append(" turns.\n");                    // start a fire in the targets hex                    Coords c = target.getPosition();                    Hex h = game.getBoard().getHex(c);                    // Unless there a fire in the hex already, start one.                    if ( !h.contains( Terrain.FIRE ) ) {                        phaseReport.append( " Fire started in hex " )                            .append( c.getBoardNum() )                            .append( ".\n" );                        h.addTerrain(new Terrain(Terrain.FIRE, 1));                    }                    game.board.addInfernoTo                        ( c, InfernoTracker.STANDARD_ROUND, hits );                    sendChangedHex(c);                    return;                }            } // End is-inferno            // targeting a hex for igniting            if( target.getTargetType() == Targetable.TYPE_HEX_IGNITE ||                target.getTargetType() == Targetable.TYPE_BLDG_IGNITE ) {                if ( !bSalvo ) {                    phaseReport.append("hits!");                }                // We handle Inferno rounds above.                int tn = wtype.getFireTN();                if (tn != TargetRoll.IMPOSSIBLE) {                    if ( bldg != null ) {                        tn += bldg.getType() - 1;                    }                    phaseReport.append( "\n" );                    tryIgniteHex( target.getPosition(), bInferno, tn );                }                return;            }                        // targeting a hex for clearing            if (target.getTargetType() == Targetable.TYPE_HEX_CLEAR) {                nDamage = nDamPerHit * hits;                if ( !bSalvo ) {                    phaseReport.append("hits!");                }                if (ae instanceof Infantry) {                    phaseReport.append("\n    But infantry cannot try to clear hexes!\n");                    return;                }                phaseReport.append("    Terrain takes " ).append( nDamage ).append( " damage.\n");                                // Any clear attempt can result in accidental ignition, even                // weapons that can't normally start fires.  that's weird.                // Buildings can't be accidentally ignited.                if ( bldg != null &&                     tryIgniteHex(target.getPosition(), bInferno, 9) ) {                    return;                }                                int tn = 14 - nDamage;                tryClearHex(target.getPosition(), tn);                                return;            }            // Targeting a building.            if ( target.getTargetType() == Targetable.TYPE_BUILDING ) {                // The building takes the full brunt of the attack.                nDamage = nDamPerHit * hits;                if ( !bSalvo ) {                    phaseReport.append( "hits." );                }                phaseReport.append( "\n        " )                    .append( damageBuilding( bldg, nDamage ) )                    .append( "\n" );                // Damage any infantry in the hex.                this.damageInfantryIn( bldg, nDamage );                // And we're done!                return;            }            // Battle Armor squads equipped with fire protection            // gear automatically avoid flaming death.            if ( wtype.hasFlag(WeaponType.F_FLAMER) &&                  target instanceof BattleArmor ) {                for ( Enumeration iter = entityTarget.getMisc();                      iter.hasMoreElements(); ) {                    Mounted mount = (Mounted) iter.nextElement();                    EquipmentType equip = mount.getType();                    if ( BattleArmor.FIRE_PROTECTION.equals                         (equip.getInternalName()) ) {                        if ( !bSalvo ) {                            phaseReport.append( "hits." );                        }                        phaseReport.append( "\n        However, " )                            .append(target.getDisplayName() )                            .append( " has fire protection gear so no damage is done.\n" );                        // A building may be damaged, even if the squad is not.                        if ( bldgAbsorbs > 0 ) {                            int toBldg = nDamPerHit * Math.min( bldgAbsorbs,                                                                hits );                            phaseReport.append( "        " )                                .append( damageBuilding( bldg, toBldg ) )                                .append( "\n" );                        }                     return;                    }                }            } // End target-may-be-immune            // Flamers do heat to mechs instead damage if the option is            // available and the mode is set.            if ( entityTarget != null &&                 (entityTarget instanceof Mech) &&                 wtype.hasFlag(WeaponType.F_FLAMER) &&                 game.getOptions().booleanOption("flamer_heat") &&                 wtype.hasModes() &&                 weapon.curMode().equals("Heat") ) {                nDamage = nDamPerHit * hits;                if ( !bSalvo ) {                    phaseReport.append( "hits." );                }                phaseReport.append("\n        Target gains ").append(nDamage).append(" more heat during heat phase.");                entityTarget.heatBuildup += nDamage;                hits = 0;            }            else if (entityTarget != null) {                HitData hit = entityTarget.rollHitLocation(toHit.getHitTable(), toHit.getSideTable());                // If a leg attacks hit a leg that isn't                // there, then hit the other leg.                if ( wtype.getInternalName().equals("LegAttack") &&                     entityTarget.getInternal(hit) <= 0 ) {                    if ( hit.getLocation() == Mech.LOC_RLEG ) {                        hit = new HitData( Mech.LOC_LLEG );                    }                    else {                        hit = new HitData( Mech.LOC_RLEG );                    }                }                // Mine Launchers automatically hit the                // CT of a Mech or the front of a Tank.                if ( wtype.getInternalName()                     .equals(BattleArmor.MINE_LAUNCHER) ) {                    if ( target instanceof Mech ) {                        hit = new HitData( Mech.LOC_CT );                    }                    else { // te instanceof Tank                        hit = new HitData( Tank.LOC_FRONT );                    }                }                // Each hit in the salvo get's its own hit location.                if (!bSalvo) {                    phaseReport.append("hits" ).append( toHit.getTableDesc() ).append( " " ).                            append( entityTarget.getLocationAbbr(hit));                }                // Special weapons do criticals instead of damage.                if ( nDamPerHit == WeaponType.DAMAGE_SPECIAL ) {                    // Do criticals.                    String specialDamage = criticalEntity( entityTarget, hit.getLocation() );                    // Replace "no effect" results with 4 points of damage.                    if ( specialDamage.endsWith(" no effect.") ) {                        // ASSUMPTION: buildings CAN'T absorb *this* damage.                        specialDamage = damageEntity(entityTarget, hit, 4);                    }                    else {                        specialDamage = "\n" + specialDamage;                    }                    // Report the result                    phaseReport.append( specialDamage );                }                else {                    // Resolve damage normally.                    nDamage = nDamPerHit * Math.min(nCluster, hits);                    // A building may be damaged, even if the squad is not.                    if ( bldgAbsorbs > 0 ) {                        int toBldg = Math.min( bldgAbsorbs, nDamage );                        nDamage -= toBldg;                        phaseReport.append( "\n        " )                            .append( damageBuilding( bldg, toBldg ) );                    }                    // A building may absorb the entire shot.                    if ( nDamage == 0 ) {                        phaseReport.append( "\n        " )                            .append( entityTarget.getDisplayName() )                            .append( " suffers no damage." );                    } else {                        phaseReport.append                            ( damageEntity(entityTarget, hit, nDamage) );                    }                }                hits -= nCluster;            }        } // Handle the next cluster.        phaseReport.append("\n");    }