if (wtype.getAmmoType() == AmmoType.T_LRM || wtype.getAmmoType() == AmmoType.T_MRM) {
if ( wtype.getAmmoType() == AmmoType.T_LRM || wtype.getAmmoType() == AmmoType.T_MRM || wtype.getAmmoType() == AmmoType.T_ATM ) {
    private void resolveWeaponAttack(WeaponResult wr, int lastEntityId) {        final Entity ae = game.getEntity(wr.waa.getEntityId());        final Entity te = game.getEntity(wr.waa.getTargetId());        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;        BattleArmor troopers = null;        final boolean isBattleArmorAttack = wtype.hasFlag(WeaponType.F_BATTLEARMOR);                if (lastEntityId != ae.getId()) {            phaseReport.append("\nWeapons fire for " + ae.getDisplayName() + "\n");        }                phaseReport.append("    " + wtype.getName() + " at " + te.getDisplayName());        // compute to-hit        ToHitData toHit = wr.toHit;        if (toHit.getValue() == ToHitData.IMPOSSIBLE) {            phaseReport.append(", but the shot is impossible (" + toHit.getDesc() + ")\n");            return;        } else if (toHit.getValue() == ToHitData.AUTOMATIC_FAIL) {            phaseReport.append(", the shot is an automatic miss (" + toHit.getDesc() + "), ");        } else {            phaseReport.append("; needs " + toHit.getValue() + ", ");        }                // 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;            }                        pilotRolls.addElement(new PilotingRollData(ae.getId(), nMod, "fired HeavyGauss unbraced"));        }                // dice have been rolled, thanks        phaseReport.append("rolls " + wr.roll + " : ");                // check for AC jams        int nShots = howManyShots(weapon, ammo);        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?        if (wr.roll < toHit.getValue()) {            // miss            phaseReport.append("misses.\n");            if (wr.amsShotDown > 0) {                phaseReport.append("\tAMS activates, firing " + wr.amsShotDown + " shot(s).\n");            }                        // if the target is in the woods and the weapon misses, and the weapon is a large weapon, set the woods on fire.            Hex targetHex = game.getBoard().getHex(te.getPosition());            if (targetHex.contains(Terrain.WOODS) && !(targetHex.contains(Terrain.FIRE))            && toHit.getValue() != TargetRoll.AUTOMATIC_FAIL) {                // 11 or 12 is the same odds as 2 or 3                if (wtype.getFireTN() != TargetRoll.IMPOSSIBLE && burn(targetHex, 11) == true)                {                    sendChangedHex(te.getPosition());                    phaseReport.append("           Missed shot sets the woods on fire! \n");                }            }// end if target has woods and no fire            return;        }                // special case NARC hits.  No damage, but a beacon is appended        if (wtype.getAmmoType() == AmmoType.T_NARC) {            te.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, bECMAffected = false;        String sSalvoType = " shot(s) ";        // Mek swarms attach the attacker to the target.        if ( wtype.getInternalName().equals("SwarmMek") ) {            // TODO : implement me            phaseReport.append( "succeeds!  Defender swarmed.\n" );            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("BAMineLauncher") ) {            hits = Compute.getBattleArmorHits( nShots );            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 = Compute.getBattleArmorHits( platoon.getShootingStrength() );        }        // 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());        } 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) {                nCluster = 5;            }            // calculate # of missiles hitting            if (wtype.getAmmoType() == AmmoType.T_LRM || wtype.getAmmoType() == AmmoType.T_SRM) {                                // check for artemis, else check for narc                Mounted mLinker = weapon.getLinkedBy();                if (mLinker != null && mLinker.getType() instanceof MiscType &&                         !mLinker.isDestroyed() && !mLinker.isMissing() &&                        mLinker.getType().hasFlag(MiscType.F_ARTEMIS)) {                                                // check ECM interference                    if (!bCheckedECM) {                        bECMAffected = Compute.isAffectedByECM(ae, ae.getPosition(), te.getPosition());                        bCheckedECM = true;                    }                    if (!bECMAffected) {                        nSalvoBonus += 2;                    }                } else if (te.isNarcedBy(ae.getOwner().getTeam())) {                    // check ECM interference                    if (!bCheckedECM) {                        bECMAffected = Compute.isAffectedByECM(ae, ae.getPosition(), te.getPosition());                        bCheckedECM = true;                    }                    if (!bECMAffected) {                        nSalvoBonus += 2;                    }                }            }                        if (wtype.getAmmoType() == AmmoType.T_SRM_STREAK) {                hits = wtype.getRackSize();            } else if (wtype.getRackSize() == 30 || wtype.getRackSize() == 40) {                // I'm going to assume these are MRMs                hits = Compute.missilesHit(wtype.getRackSize() / 2) + Compute.missilesHit(wtype.getRackSize() / 2);            } else if ( ae instanceof BattleArmor ) {                // Battle Armor units multiply their racksize by the                // # of men shooting and they can't use NARCs.                platoon = (Infantry) ae;                int temp = wtype.getRackSize() * platoon.getShootingStrength();                // Account for more than 20 missles hitting.                hits = 0;                while ( temp > 20 ) {                    hits += Compute.missilesHit( 20 );                    temp -= 20;                }                hits += Compute.missilesHit( temp );                            } else {                hits = Compute.missilesHit(wtype.getRackSize(), nSalvoBonus);            }            // Advanced SRM's don't hit with an odd # 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.hasFlag(AmmoType.F_CLUSTER)) {            // Cluster shots break into single point clusters.            bSalvo = true;            hits = Compute.missilesHit(wtype.getRackSize());            nDamPerHit = 1;        } else if (nShots > 1) {            // this should handle multiple attacks from ultra and rotary ACs            bSalvo = true;            hits = Compute.missilesHit(nShots);        } else if (atype != null && atype.hasFlag(AmmoType.F_MG) &&                   !isWeaponInfantry && (te instanceof Infantry) &&                   !(te instanceof BattleArmor) ) {            // Mech and Vehicle MGs do *DICE* of damage to PBI.            // 2002-10-24 Suvarov454 : no need for so many lines in the report.            nDamPerHit = Compute.d6(wtype.getDamage());            phaseReport.append( "riddles the target with " +                 nDamPerHit + sSalvoType + "and " );        }        else if (wtype.getAmmoType() == AmmoType.T_GAUSS_HEAVY) {            // HGR does range-dependent damage            int nRange = ae.getPosition().distance(te.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;        }        // Battle Armor MGs do one die of damage per hit to PBI.        if ( wtype.getAmmoType() == AmmoType.T_BA_MG &&             (te instanceof Infantry) && !(te instanceof BattleArmor) ) {            nDamPerHit = Compute.d6(hits);            phaseReport.append( "riddles the target with " +                 nDamPerHit + sSalvoType + "and " );            hits = 1;            bSalvo = false;        }        // Report the number of hits.        if (bSalvo) {            phaseReport.append(hits + sSalvoType + "hit" + toHit.getTableDesc());            if (bECMAffected) {                phaseReport.append(" (ECM prevents bonus)");            }            if (nSalvoBonus > 0) {                phaseReport.append(" (w/ +").append(nSalvoBonus).append(" bonus)");            }            phaseReport.append(".");                        if (wr.amsShotDown > 0) {                phaseReport.append("\n\tAMS shoots down " + wr.amsShotDown + " missile(s).");                hits -= wr.amsShotDown;            }        }        // for each cluster of hits, do a chunk of damage        while (hits > 0) {            int nDamage;            // if we're targeting a hex, then             if(te instanceof HexEntity) {              nDamage = nDamPerHit * hits;              phaseReport.append("hits!\n");              phaseReport.append("    Terrain takes " + nDamage + " damage.\n");              Coords c = te.getPosition();              Hex h = game.getBoard().getHex(c);              if(!h.contains(Terrain.WOODS)) return; // only woods can be lit on fire or cleared at the moment              int TN = 14 - nDamage;              if(!wtype.hasFlag(WeaponType.F_FLAMER)) {                int Woods = h.levelOf(Terrain.WOODS);                if(Woods < 1) return;                int woodsRoll = Compute.d6(2);                phaseReport.append("    Checking to clear woods; needs " + TN + ", rolls " + woodsRoll + ": ");                if(woodsRoll >= TN) {                  if(Woods > 1) {                     h.removeTerrain(Terrain.WOODS);                     h.addTerrain(new Terrain(Terrain.WOODS, Woods - 1));                     phaseReport.append(" Heavy Woods converted to Light Woods!\n");                  }                  else if(Woods == 1) {                     h.removeTerrain(Terrain.WOODS);                     h.addTerrain(new Terrain(Terrain.ROUGH, 1));                     phaseReport.append(" Light Woods converted to Rough!\n");                  }                  sendChangedHex(c);                } else {                  phaseReport.append(" fails!\n");                }              }              TN = wtype.getFireTN();              phaseReport.append("    Checking to start fire in hex; needs " + TN + ", ");              int fireRoll = Compute.d6(2);              phaseReport.append("rolls " + fireRoll + " : ");              if(fireRoll >= TN) {                 phaseReport.append(" Fire started!\n");                 h.addTerrain(new Terrain(Terrain.FIRE, 1));                 sendChangedHex(c);              }              else {                 phaseReport.append(" No fire.\n");              }                           return;            }            // Flamers do heat, not damage.            if (wtype.hasFlag(WeaponType.F_FLAMER) && game.getOptions().booleanOption("flamer_heat")) {                nDamage = nDamPerHit * hits;                phaseReport.append("\n        Target gains ").append(nDamage).append(" more heat during heat phase.");                te.heatBuildup += nDamage;                hits = 0;            }            else {                HitData hit = te.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") &&                     te.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("BAMineLauncher") ) {                    if ( te 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" + toHit.getTableDesc() + " " + te.getLocationAbbr(hit));                }                // Special weapons do criticals instead of damage.                if ( nDamPerHit == WeaponType.DAMAGE_SPECIAL ) {                    // Do criticals.                    String specialDamage = criticalEntity( te, hit.getLocation() );                    // Replace "no effect" results with 4 points of damage.                    if ( specialDamage.endsWith(" no effect.") ) {                        specialDamage = damageEntity(te, hit, 4);                    }                    else {                        specialDamage = "\n" + specialDamage;                    }                    // Report the result                    phaseReport.append( specialDamage );                }                else {                    // Resolve damage normally.                    nDamage = nDamPerHit * Math.min(nCluster, hits);                    phaseReport.append(damageEntity(te, hit, nDamage));                }                hits -= nCluster;            }        } // Handle the next cluster.        phaseReport.append("\n");    }