Package megamek.common

Examples of megamek.common.HitData


            if (ctrlroll < psr.getValue()) {
                r.choose(false);
                addReport(r);
                // damage the unit
                int damage = 10 * (psr.getValue() - ctrlroll);
                HitData hit = a.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
                addReport(damageEntity(unit, hit, damage));
                // did we destroy the unit?
                if (unit.isDoomed()) {
                    // Clean out the entity.
                    unit.setDestroyed(true);
                    game.moveToGraveyard(unit.getId());
                    send(createRemoveEntityPacket(unit.getId()));
                }
            } else {
                // avoided damage
                r.choose(true);
                addReport(r);
            }
        }

        // launching from an OOC vessel causes damage
        // same thing if faster than 2 velocity in atmosphere
        if ((((Aero) unloader).isOutControlTotal() && !unit.isDoomed()) || ((((Aero) unloader).getCurrentVelocity() > 2) && game.getBoard().inAtmosphere())) {
            int damroll = Compute.d6(2);
            int damage = damroll * 10;
            r = new Report(9385);
            r.subject = unit.getId();
            r.add(unit.getDisplayName());
            r.add(damage);
            addReport(r);
            HitData hit = a.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
            addReport(damageEntity(unit, hit, damage));
            // did we destroy the unit?
            if (unit.isDoomed()) {
                // Clean out the entity.
                unit.setDestroyed(true);
View Full Code Here


                        r.newlines = 0;
                        addReport(r);

                        // Infantry don't have different
                        // tables for punches and kicks
                        HitData hit = target.rollHitLocation(ToHitData.HIT_NORMAL, Compute.targetSideTable(entity, target));
                        hit.setGeneralDamageType(HitData.DAMAGE_PHYSICAL);
                        // Damage equals tonnage, divided by 5.
                        // ASSUMPTION: damage is applied in one hit.
                        addReport(damageEntity(target, hit, Math.round(entity.getWeight() / 5)));
                        addNewLines();
                    }

                    // Has the target been destroyed?
                    if (target.isDoomed()) {

                        // Has the target taken a turn?
                        if (!target.isDone()) {

                            // Dead entities don't take turns.
                            game.removeTurnFor(target);
                            send(createTurnVectorPacket());

                        } // End target-still-to-move

                        // Clean out the entity.
                        target.setDestroyed(true);
                        game.moveToGraveyard(target.getId());
                        send(createRemoveEntityPacket(target.getId()));
                    }

                    // Update the target's position,
                    // unless it is off the game map.
                    if (!game.isOutOfGame(target)) {
                        entityUpdate(target.getId());
                    }

                } // Check the next entity in the hex.

                if (skidChargeHit) {
                    // HACK: set the entities position to that
                    // hex's coords, because we had to move the entity
                    // back earlier for the other targets
                    entity.setPosition(nextPos);
                }

                for (Entity e : avoidedChargeUnits) {
                    GameTurn newTurn = new GameTurn.SpecificEntityTurn(e.getOwner().getId(), e.getId());
                    game.insertNextTurn(newTurn);
                    send(createTurnVectorPacket());
                }
            }

            // Handle the building in the hex.
            if (bldg != null) {

                // Report that the entity has entered the bldg.
                r = new Report(2080);
                r.subject = entity.getId();
                r.indent();
                r.add(bldg.getName());
                r.add(nextPos.getBoardNum(), true);
                addReport(r);

                // If the building hasn't already suffered
                // damage, then apply charge damage to the
                // building and displace the entity inside.
                // ASSUMPTION: you don't charge the building
                // if Tanks or Mechs were charged.
                int chargeDamage = ChargeAttackAction.getDamageFor(entity, game.getOptions().booleanOption("tacops_charge_damage"), entity.delta_distance);
                if (!bldgSuffered) {
                    Vector<Report> reports = damageBuilding(bldg, chargeDamage, nextPos);
                    for (Report report : reports) {
                        report.subject = entity.getId();
                    }
                    addReport(reports);

                    // Apply damage to the attacker.
                    int toAttacker = ChargeAttackAction.getDamageTakenBy(entity, bldg, nextPos);
                    HitData hit = entity.rollHitLocation(ToHitData.HIT_NORMAL, entity.sideTable(nextPos));
                    hit.setGeneralDamageType(HitData.DAMAGE_PHYSICAL);
                    addReport(damageEntity(entity, hit, toAttacker));
                    addNewLines();

                    entity.setPosition(nextPos);
                    entity.setElevation(nextElevation);
                    addReport(doEntityDisplacementMinefieldCheck(entity, curPos, nextPos, nextElevation));
                    curPos = nextPos;
                } // End buildings-suffer-too

                // Any infantry in the building take damage
                // equal to the building being charged.
                // ASSUMPTION: infantry take no damage from the
                // building absorbing damage from
                // Tanks and Mechs being charged.
                damageInfantryIn(bldg, chargeDamage, nextPos);

                // If a building still stands, then end the skid,
                // and add it to the list of affected buildings.
                if (bldg.getCurrentCF(nextPos) > 0) {
                    stopTheSkid = true;
                    addAffectedBldg(bldg, false);
                } else {
                    // otherwise it collapses immediately on our head
                    checkForCollapse(bldg, game.getPositionMap(), nextPos, true);
                }

            } // End handle-building.

            // Do we stay in the current hex and stop skidding?
            if (stopTheSkid) {
                break;
            }

            // Update entity position and elevation
            entity.setPosition(nextPos);
            entity.setElevation(nextElevation);
            addReport(doEntityDisplacementMinefieldCheck(entity, curPos, nextPos, nextElevation));
            skidDistance++;

            // Check for collapse of any building the entity might be on
            Building roof = game.getBoard().getBuildingAt(nextPos);
            if (roof != null) {
                if (checkForCollapse(roof, game.getPositionMap(), nextPos, true)) {
                    break; // stop skidding if the building collapsed
                }
            }

            // Can the skiding entity enter the next hex from this?
            // N.B. can skid along roads.
            if ((entity.isHexProhibited(curHex) || entity.isHexProhibited(nextHex)) && !Compute.canMoveOnPavement(game, curPos, nextPos, step.getParentUpToThisStep())) {
                // Update report.
                r = new Report(2040);
                r.subject = entity.getId();
                r.indent();
                r.add(nextPos.getBoardNum(), true);
                addReport(r);

                // If the prohibited terrain is water, entity is destroyed
                if ((nextHex.terrainLevel(Terrains.WATER) > 0) && (entity instanceof Tank) && (entity.getMovementMode() != IEntityMovementMode.HOVER) && (entity.getMovementMode() != IEntityMovementMode.WIGE)) {
                    addReport(destroyEntity(entity, "skidded into a watery grave", false, true));
                }

                // otherwise, damage is weight/5 in 5pt clusters
                int damage = ((int) entity.getWeight() + 4) / 5;
                while (damage > 0) {
                    addReport(damageEntity(entity, entity.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT), Math.min(5, damage)));
                    damage -= 5;
                }
                // and unit is immobile
                if (entity instanceof Tank) {
                    ((Tank) entity).immobilize();
                }

                // Stay in the current hex and stop skidding.
                break;
            }

            if ((nextHex.terrainLevel(Terrains.WATER) > 0) && (entity.getMovementMode() != IEntityMovementMode.HOVER) && (entity.getMovementMode() != IEntityMovementMode.WIGE)) {
                // water ends the skid
                break;
            }

            // check for breaking magma crust
            if ((nextHex.terrainLevel(Terrains.MAGMA) == 1) && (nextElevation == 0)) {
                int roll = Compute.d6(1);
                r = new Report(2395);
                r.addDesc(entity);
                r.add(roll);
                r.subject = entity.getId();
                addReport(r);
                if (roll == 6) {
                    nextHex.removeTerrain(Terrains.MAGMA);
                    nextHex.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.MAGMA, 2));
                    sendChangedHex(curPos);
                    for (Enumeration<Entity> e = game.getEntities(curPos); e.hasMoreElements();) {
                        Entity en = e.nextElement();
                        if (en != entity) {
                            doMagmaDamage(en, false);
                        }
                    }
                }
            }

            // check for entering liquid magma
            if ((nextHex.terrainLevel(Terrains.MAGMA) == 2) && (nextElevation == 0)) {
                doMagmaDamage(entity, false);
            }

            // is the next hex a swamp?
            PilotingRollData rollTarget = entity.checkBogDown(step, nextHex, curPos, nextPos, step.getElevation(), Compute.canMoveOnPavement(game, curPos, nextPos, step.getParentUpToThisStep()));
            if (rollTarget.getValue() != TargetRoll.CHECK_FALSE) {
                //Taharqa: According to TacOps, you automatically stick if you are skidding, (pg. 63)
                //if (0 < doSkillCheckWhileMoving(entity, curPos, nextPos, rollTarget, false)) {
                    entity.setStuck(true);
                    r = new Report(2081);
                    r.subject = entity.getId();
                    r.add(entity.getDisplayName(), true);
                    addReport(r);
                    //check for quicksand
                    addReport (checkQuickSand(nextPos));
                    // check for accidental stacking violation
                    Entity violation = Compute.stackingViolation(game, entity.getId(), curPos);
                    if (violation != null) {
                        // target gets displaced, because of low elevation
                        Coords targetDest = Compute.getValidDisplacement(game, entity.getId(), curPos, direction);
                        addReport(doEntityDisplacement(violation, curPos, targetDest, new PilotingRollData(violation.getId(), 0, "domino effect")));
                        // Update the violating entity's postion on the client.
                        entityUpdate(violation.getId());
                    }
                    // stay here and stop skidding, see bug 1115608
                    break;
               // }
            }

            // Update the position and keep skidding.
            curPos = nextPos;
            curHex = nextHex;
            r = new Report(2085);
            r.subject = entity.getId();
            r.indent();
            r.add(curPos.getBoardNum(), true);
            addReport(r);

        } // Handle the next skid hex.

        // If the skidding entity violates stacking,
        // displace targets until it doesn't.
        curPos = entity.getPosition();
        Entity target = Compute.stackingViolation(game, entity.getId(), curPos);
        while (target != null) {
            nextPos = Compute.getValidDisplacement(game, target.getId(), target.getPosition(), direction);
            // ASSUMPTION
            // There should always be *somewhere* that
            // the target can go... last skid hex if
            // nothing else is available.
            if (null == nextPos) {
                // But I don't trust the assumption fully.
                // Report the error and try to continue.
                System.err.println("The skid of " + entity.getShortName() + " should displace " + target.getShortName() + " in hex " + curPos.getBoardNum() + " but there is nowhere to go.");
                break;
            }
            // indent displacement
            r = new Report(1210, Report.PUBLIC);
            r.indent();
            r.newlines = 0;
            addReport(r);
            addReport(doEntityDisplacement(target, curPos, nextPos, null));
            addReport(doEntityDisplacementMinefieldCheck(entity, curPos, nextPos, entity.getElevation()));
            target = Compute.stackingViolation(game, entity.getId(), curPos);
        }

        // Mechs suffer damage for every hex skidded.
        if (entity instanceof Mech) {
            // Calculate one half falling damage times skid length.
            int damage = skidDistance * (int) Math.ceil(Math.round(entity.getWeight() / 10.0) / 2.0);

            // report skid damage
            r = new Report(2090);
            r.subject = entity.getId();
            r.indent();
            r.addDesc(entity);
            r.add(damage);
            addReport(r);

            // standard damage loop
            // All skid damage is to the front.
            while (damage > 0) {
                int cluster = Math.min(5, damage);
                HitData hit = entity.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
                hit.setGeneralDamageType(HitData.DAMAGE_PHYSICAL);
                addReport(damageEntity(entity, hit, cluster));
                damage -= cluster;
            }
            addNewLines();
        }
View Full Code Here

                if (roll >= 9) {
                    r = new Report(3706);
                    r.addDesc(entityTarget);
                    // shut down for rest of scenario, so we actually kill it
                    // TODO: fix for salvage purposes
                    HitData targetTrooper = entityTarget.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
                    r.add(entityTarget.getLocationAbbr(targetTrooper));
                    vPhaseReport.add(r);
                    vPhaseReport.addAll(server.criticalEntity(ae, targetTrooper.getLocation(), 0, false, false));
                    done = true;
                }
            } else if (entityTarget instanceof Mech) {
                if (((Mech)entityTarget).isIndustrial()) {
                    if (roll >= 11) {
View Full Code Here

            FighterSquadron fs = (FighterSquadron)te;
            if(fs.getFighters().size() < 1) {
                return vDesc;
            }
            Aero fighter = fs.getFighter(hit.getLocation());
            HitData new_hit = fighter.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
            new_hit.setBoxCars(hit.rolledBoxCars());
            new_hit.setGeneralDamageType(hit.getGeneralDamageType());
            new_hit.setCapital(hit.isCapital());
            new_hit.setCapMisCritMod(hit.getCapMisCritMod());
            new_hit.setSingleAV(hit.getSingleAV());
            return damageEntity(fighter, new_hit, damage, ammoExplosion, bFrag, damageIS, areaSatArty, throughFront, underWater, nukeS2S);
        }

        // This is good for shields if a shield absorps the hit it shouldn't
        // effect the pilot.
        // TC SRM's that hit the head do external and internal damage but its
        // one hit and shouldn't cause
        // 2 hits to the pilot.
        boolean isHeadHit = (te instanceof Mech) && (((Mech) te).getCockpitType() != Mech.COCKPIT_TORSO_MOUNTED) && (hit.getLocation() == Mech.LOC_HEAD) && ((hit.getEffect() & HitData.EFFECT_NO_CRITICALS) != HitData.EFFECT_NO_CRITICALS);

        // booleans to indicate criticals for AT2
        boolean critSI = false;
        boolean critThresh = false;

        //get the relevant damage for damage thresholding
        int threshDamage = damage;
        //weapon groups only get the damage of one weapon
        if(hit.getSingleAV() > -1) {
            threshDamage = hit.getSingleAV();
        }

        // is this capital-scale damage
        boolean isCapital = hit.isCapital();

        // check capital/standard damage
        if (isCapital && !te.isCapitalScale()) {
            damage = 10 * damage;
            threshDamage = 10 * threshDamage;
        }
        if (!isCapital && te.isCapitalScale()) {
                damage = (int)Math.round(damage / 10.0);
                threshDamage = (int)Math.round(threshDamage / 10.0);
        }

        int damage_orig = damage;

        // show Locations which have rerolled with Edge
        HitData undoneLocation = hit.getUndoneLocation();
        while (undoneLocation != null) {
            r = new Report(6500);
            r.subject = te_n;
            r.indent(2);
            r.newlines = 0;
            r.addDesc(te);
            r.add(te.getLocationAbbr(undoneLocation));
            vDesc.addElement(r);
            undoneLocation = undoneLocation.getUndoneLocation();
        } // while
        // if edge was uses, give at end overview of remainings
        if (hit.getUndoneLocation() != null) {
            r = new Report(6510);
            r.subject = te_n;
            r.indent(2);
            r.newlines = 0;
            r.addDesc(te);
            r.add(te.crew.getOptions().intOption("edge"));
            vDesc.addElement(r);
        } // if

        boolean autoEject = false;
        if (ammoExplosion) {
            if (te instanceof Mech) {
                Mech mech = (Mech) te;
                if (mech.isAutoEject()) {
                    autoEject = true;
                    vDesc.addAll(ejectEntity(te, true));
                }
            }
        }
        boolean isBattleArmor = te instanceof BattleArmor;
        boolean isPlatoon = !isBattleArmor && (te instanceof Infantry);
        boolean isFerroFibrousTarget = false;
        boolean wasDamageIS = false;
        boolean tookInternalDamage = damageIS;
        IHex te_hex = null;

        boolean hardenedArmor = false;
        boolean reflectiveArmor = false;
        boolean reactiveArmor = false;

        if ( ((te instanceof Mech) || (te instanceof Tank)) && (te.getArmorType() == EquipmentType.T_ARMOR_HARDENED)) {
            hardenedArmor = true;
        }

        if (((te instanceof Mech) || (te instanceof Tank)) && (te.getArmorType() == EquipmentType.T_ARMOR_REFLECTIVE)) {
            reflectiveArmor = true;
        }

        if (((te instanceof Mech) || (te instanceof Tank)) && (te.getArmorType() == EquipmentType.T_ARMOR_REACTIVE)) {
            reactiveArmor = true;
        }

        int crits = ((hit.getEffect() & HitData.EFFECT_CRITICAL) == HitData.EFFECT_CRITICAL) && !hardenedArmor ? 1 : 0;
        int specCrits = ((hit.getEffect() & HitData.EFFECT_CRITICAL) == HitData.EFFECT_CRITICAL) && hardenedArmor ? 1 : 0;
        HitData nextHit = null;

        // Some "hits" on a Protomech are actually misses.
        if ((te instanceof Protomech) && (hit.getLocation() == Protomech.LOC_NMISS)) {
            r = new Report(6035);
            r.subject = te_n;
            r.indent(2);
            r.newlines = 0;
            vDesc.addElement(r);
            return vDesc;
        }

        // check for critical hit/miss vs. a BA
        if ((crits > 0) && (te instanceof BattleArmor)) {
            // possible critical miss if the rerolled location isn't alive
            if ((hit.getLocation() >= te.locations()) || (te.getInternal(hit.getLocation()) <= 0)) {
                r = new Report(6037);
                r.add(hit.getLocation());
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
                return vDesc;
            }
            // otherwise critical hit
            r = new Report(6225);
            r.add(te.getLocationAbbr(hit));
            r.subject = te_n;
            r.indent(2);
            r.newlines = 0;
            vDesc.addElement(r);

            crits = 0;
            damage = Math.max(te.getInternal(hit.getLocation()) + te.getArmor(hit.getLocation()), damage);
        }

        if ((te.getArmor(hit) > 0) && ((te.getArmorType() == EquipmentType.T_ARMOR_FERRO_FIBROUS) || (te.getArmorType() == EquipmentType.T_ARMOR_LIGHT_FERRO) || (te.getArmorType() == EquipmentType.T_ARMOR_HEAVY_FERRO))) {
            isFerroFibrousTarget = true;
        }

        // Is the infantry in the open?
        if (isPlatoon && !te.isDestroyed()
                && !te.isDoomed() && (((Infantry) te).getDugIn() != Infantry.DUG_IN_COMPLETE)
                && !te.crew.getOptions().booleanOption("dermal_armor")) {
            te_hex = game.getBoard().getHex(te.getPosition());
            if ((te_hex != null) && !te_hex.containsTerrain(Terrains.WOODS) && !te_hex.containsTerrain(Terrains.JUNGLE) && !te_hex.containsTerrain(Terrains.ROUGH) && !te_hex.containsTerrain(Terrains.RUBBLE) && !te_hex.containsTerrain(Terrains.SWAMP) && !te_hex.containsTerrain(Terrains.BUILDING) && !te_hex.containsTerrain(Terrains.FUEL_TANK) && !te_hex.containsTerrain(Terrains.FORTIFIED) && !ammoExplosion) {
                // PBI. Damage is doubled.
                damage *= 2;
                r = new Report(6040);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
            }
        }
        // Is the infantry in vacuum?
        if ((isPlatoon || isBattleArmor) && !te.isDestroyed() && !te.isDoomed()
                && game.getPlanetaryConditions().isVacuum()) {
            // PBI. Double damage.
            damage *= 2;
            r = new Report(6041);
            r.subject = te_n;
            r.indent(2);
            r.newlines = 0;
            vDesc.addElement(r);
        }
        // If dealing with fragmentation missiles,
        // it does double damage to infantry...
        // We're actually going to abuse this for AX-head warheads, too, so as
        // to not add another parameter.
        switch (bFrag) {
        case ANTI_INFANTRY:
            if(isPlatoon && te.crew.getOptions().booleanOption("dermal_armor")) {
                int reduce = Math.min(damage - 1, Compute.d6());
                damage -= reduce;
                r = new Report(6042);
                r.subject = te_n;
                r.add(reduce);
                r.add(damage);
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
            }
            break;
        case FRAGMENTATION:
            if (!isPlatoon) {
                damage = 0;
                r = new Report(6050);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
            }
            break;
        case FLECHETTE:
            if (!isPlatoon && !isBattleArmor) {
                damage /= 2;
                r = new Report(6060);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
            } else if (isPlatoon && !isBattleArmor) {
                r = new Report(6055);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
            }
            break;
        case ACID:
            if (isFerroFibrousTarget) {
                damage = te.getArmor(hit) >= 3 ? 3 : te.getArmor(hit);
                r = new Report(6061);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                r.add(damage);
                vDesc.addElement(r);
            } else {
                r = new Report(6062);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
            }
            break;
        case INCENDIARY:
            // Incendiary AC ammo does +2 damage to unarmoured infantry
            if (isPlatoon) {
                damage += 2;
                r = new Report(6064);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                vDesc.addElement(r);
            }
            break;
        case ANTI_TSM:
            te.hitThisRoundByAntiTSM = true;
        default:
            // We can ignore this.
            break;
        }

        //check for infantry armor
    /*
        if(isPlatoon) {
            damage = (int)Math.ceil(damage / 2.0);
            r = new Report(6043);
            r.subject = te_n;
            r.indent(2);
            r.newlines = 0;
            r.add(damage);
            vDesc.addElement(r);
        }
*/

        // adjust VTOL rotor damage
        if ((te instanceof VTOL) && (hit.getLocation() == VTOL.LOC_ROTOR)) {
            damage = (damage + 9) / 10;
        }

        // save EI status, in case sensors crit destroys it
        final boolean eiStatus = te.hasActiveEiCockpit();
        // BA using EI implants receive +1 damage from attacks
        if (!(te instanceof Mech) && !(te instanceof Protomech) && eiStatus) {
            damage += 1;
        }

        // check for case on Aeros
        if (te instanceof Aero) {
            Aero a = (Aero) te;
            if (ammoExplosion && a.hasCase()) {
                // damage should be reduced by a factor of 2 for ammo explosions
                // according to p. 161, TW
                damage /= 2;
                r = new Report(9010);
                r.subject = te_n;
                r.add(damage);
                r.indent(3);
                r.newlines = 0;
                vDesc.addElement(r);
            }
        }

        // Allocate the damage
        while (damage > 0) {

            // first check for ammo explosions on aeros separately, because it
            // must be done before
            // standard to capital damage conversions
            if ((te instanceof Aero) && (hit.getLocation() == Aero.LOC_AFT) && !damageIS) {
                for (Mounted mAmmo : te.getAmmo()) {
                    if (mAmmo.isDumping() && !mAmmo.isDestroyed()
                            && !mAmmo.isHit() && !(mAmmo.getType() instanceof BombType)) {
                        // doh. explode it
                        vDesc.addAll(explodeEquipment(te, mAmmo.getLocation(), mAmmo));
                        mAmmo.setHit(true);
                    }
                }
            }

            if (te instanceof Aero) {
                // chance of a critical if damage greater than threshold
                Aero a = (Aero) te;
                if ((threshDamage > a.getThresh(hit.getLocation())) && !te.isCapitalFighter()) {
                    critThresh = true;
                    a.setCritThresh(true);
                }

                if ((threshDamage >= 2) && te.isCapitalFighter()) {
                    critThresh = true;
                    a.setCritThresh(true);
                }
            }

            //Capital fighters receive damage differently
            if (te.isCapitalFighter()) {
                Aero a = (Aero)te;
                a.setCurrentDamage(a.getCurrentDamage() + damage);
                a.setCapArmor(a.getCapArmor() - damage);
                r = new Report(9065);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                r.addDesc(te);
                r.add(damage);
                vDesc.addElement(r);
                r = new Report(6085);
                r.subject = te_n;
                r.newlines = 0;
                r.add(Math.max(a.getCapArmor(), 0));
                vDesc.addElement(r);
                // check to see if this detroyed the entity
                if (a.getCapArmor() <= 0) {
                    vDesc.addAll(destroyEntity(te, "structural integrity collapse"));
                    a.setCapArmor(0);
                }
                damage = 0;
                //check for crits
                checkAeroCrits(vDesc, (Aero)te, hit, damage_orig, critThresh, critSI, ammoExplosion, nukeS2S);
                return vDesc;
            }

            if (!((te instanceof Aero) && ammoExplosion)) {
                // report something different for Aero ammo explosions
                r = new Report(6065);
                r.subject = te_n;
                r.indent(2);
                r.newlines = 0;
                r.addDesc(te);
                r.add(damage);
                if (damageIS) {
                    r.messageId = 6070;
                }
                r.add(te.getLocationAbbr(hit));
                vDesc.addElement(r);
            }

            // was the section destroyed earlier this phase?
            if (te.getInternal(hit) == IArmorState.ARMOR_DOOMED) {
                // cannot transfer a through armor crit if so
                crits = 0;
            }

            // here goes the fun :)
            // Shields take damage first then cowls then armor whee
            // Shield does not protect from ammo explosions or falls.
            if (!ammoExplosion && !hit.isFallDamage() && !damageIS && te.hasShield() && ((hit.getEffect() & HitData.EFFECT_NO_CRITICALS) != HitData.EFFECT_NO_CRITICALS)) {
                Mech me = (Mech) te;
                int damageNew = me.shieldAbsorptionDamage(damage, hit.getLocation(), hit.isRear());
                // if a shield absorbed the damage then lets tell the world
                // about it.
                if (damageNew != damage) {
                    int absorb = damage - damageNew;
                    te.damageThisPhase += absorb;
                    damage = damageNew;

                    r = new Report(3530);
                    r.subject = te_n;
                    r.indent(3);
                    r.newlines = 0;
                    r.add(absorb);
                    vDesc.addElement(r);

                    if (damage <= 0) {
                        crits = 0;
                        specCrits = 0;
                        isHeadHit = false;
                    }
                }
            }

            // Armored Cowl may absorb some damage from hit
            if (te instanceof Mech) {
                Mech me = (Mech) te;
                if (me.hasCowl() && (hit.getLocation() == Mech.LOC_HEAD) && !throughFront) {
                    int damageNew = me.damageCowl(damage);
                    int damageDiff = damage - damageNew;
                    me.damageThisPhase += damageDiff;
                    damage = damageNew;

                    r = new Report(3520);
                    r.subject = te_n;
                    r.indent(3);
                    r.newlines = 0;
                    r.add(damageDiff);
                    vDesc.addElement(r);
                }
            }

            if (!ammoExplosion && !damageIS && ((hit.getEffect() & HitData.EFFECT_NO_CRITICALS) != HitData.EFFECT_NO_CRITICALS)) {
                damage = te.getDamageReductionFromModularArmor(hit.getLocation(), damage, vDesc);
            }

            // Destroy searchlights on 7+ (torso hits on mechs)
            boolean spotlightHittable = false;
            if (te.hasSpotlight()) {
                spotlightHittable = true;
                int loc = hit.getLocation();
                if (te instanceof Mech) {
                    if ((loc != Mech.LOC_CT) && (loc != Mech.LOC_LT) && (loc != Mech.LOC_RT)) {
                        spotlightHittable = false;
                    }
                } else if (te instanceof Tank) {
                    if ((loc != Tank.LOC_FRONT) && (loc != Tank.LOC_RIGHT) && (loc != Tank.LOC_LEFT)) {
                        spotlightHittable = false;
                    }
                }
                if (spotlightHittable) {
                    int spotroll = Compute.d6(2);
                    r = new Report(6072);
                    r.indent(2);
                    r.subject = te_n;
                    r.add(spotroll);
                    vDesc.addElement(r);
                    if (spotroll >= 7) {
                        r = new Report(6071);
                        r.subject = te_n;
                        r.indent(2);
                        vDesc.addElement(r);
                        te.setSpotlightState(false);
                        te.setSpotlight(false);
                    }
                }
            }

            // Does an exterior passenger absorb some of the damage?
            if (!damageIS) {
                int nLoc = hit.getLocation();
                Entity passenger = te.getExteriorUnitAt(nLoc, hit.isRear());
                // Does an exterior passenger absorb some of the damage?
                if (!ammoExplosion && (null != passenger) && (Compute.d6() >= 5) && !passenger.isDoomed() && (bFrag != DamageType.IGNORE_PASSENGER)) {
                    // Yup. Roll up some hit data for that passenger.
                    r = new Report(6075);
                    r.subject = passenger.getId();
                    r.indent(3);
                    r.addDesc(passenger);
                    vDesc.addElement(r);

                    HitData passHit = passenger.getTrooperAtLocation(hit, te);

                    // How much damage will the passenger absorb?
                    int absorb = 0;
                    HitData nextPassHit = passHit;
                    do {
                        if (0 < passenger.getArmor(nextPassHit)) {
                            absorb += passenger.getArmor(nextPassHit);
                        }
                        if (0 < passenger.getInternal(nextPassHit)) {
                            absorb += passenger.getInternal(nextPassHit);
                        }
                        nextPassHit = passenger.getTransferLocation(nextPassHit);
                    } while ((damage > absorb) && (nextPassHit.getLocation() >= 0));

                    // Damage the passenger.
                    vDesc.addAll(damageEntity(passenger, passHit, damage));

                    // Did some damage pass on?
                    if (damage > absorb) {
                        // Yup. Remove the absorbed damage.
                        damage -= absorb;
                        r = new Report(6080);
                        r.subject = te_n;
                        r.indent(1);
                        r.add(damage);
                        r.addDesc(te);
                        vDesc.addElement(r);
                    } else {
                        // Nope. Return our description.
                        return vDesc;
                    }

                } // End nLoc-has-exterior-passenger

                boolean bTorso = (nLoc == Mech.LOC_CT) || (nLoc == Mech.LOC_RT) || (nLoc == Mech.LOC_LT);

                // Does a swarming unit absorb damage?
                int swarmer = te.getSwarmAttackerId();
                if ((!(te instanceof Mech) || bTorso) && (swarmer != Entity.NONE) && ((hit.getEffect() & HitData.EFFECT_CRITICAL) == 0) && (Compute.d6() >= 5) && (bFrag != DamageType.IGNORE_PASSENGER)) {
                    Entity swarm = game.getEntity(swarmer);
                    // Yup. Roll up some hit data for that passenger.
                    r = new Report(6076);
                    r.subject = swarmer;
                    r.indent(3);
                    r.addDesc(swarm);
                    vDesc.addElement(r);

                    HitData passHit = swarm.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);

                    // How much damage will the swarm absorb?
                    int absorb = 0;
                    HitData nextPassHit = passHit;
                    do {
                        if (0 < swarm.getArmor(nextPassHit)) {
                            absorb += swarm.getArmor(nextPassHit);
                        }
                        if (0 < swarm.getInternal(nextPassHit)) {
                            absorb += swarm.getInternal(nextPassHit);
                        }
                        nextPassHit = swarm.getTransferLocation(nextPassHit);
                    } while ((damage > absorb) && (nextPassHit.getLocation() >= 0));

                    // Damage the swarm.
                    vDesc.addAll(damageEntity(swarm, passHit, damage));

                    // Did some damage pass on?
                    if (damage > absorb) {
                        // Yup. Remove the absorbed damage.
                        damage -= absorb;
                        r = new Report(6080);
                        r.subject = te_n;
                        r.indent(1);
                        r.add(damage);
                        r.addDesc(te);
                        vDesc.addElement(r);
                    } else {
                        // Nope. Return our description.
                        return vDesc;
                    }
                }

                // is this a mech dumping ammo being hit in the rear torso?
                if (((te instanceof Mech) && hit.isRear() && bTorso) || ((te instanceof Tank) && (hit.getLocation() == Tank.LOC_REAR))) {
                    for (Mounted mAmmo : te.getAmmo()) {
                        if (mAmmo.isDumping() && !mAmmo.isDestroyed() && !mAmmo.isHit()) {
                            // doh. explode it
                            vDesc.addAll(explodeEquipment(te, mAmmo.getLocation(), mAmmo));
                            mAmmo.setHit(true);
                        }
                    }
                }
            }

            // is there armor in the location hit?
            if (!ammoExplosion && (te.getArmor(hit) > 0) && !damageIS) {
                int tmpDamageHold = -1;
                int origDamage = damage;

                // If the target has hardened armor, we need to adjust damage.
                if (hardenedArmor && (hit.getGeneralDamageType() != HitData.DAMAGE_ARMOR_PIERCING) && (hit.getGeneralDamageType() != HitData.DAMAGE_ARMOR_PIERCING_MISSILE)) {
                    tmpDamageHold = damage;
                    damage = (int) Math.ceil(((double) damage) / 2);
                    r = new Report(6069);
                    r.subject = te_n;
                    r.indent(2);
                    r.newlines = 0;
                    r.add(damage);
                    vDesc.addElement(r);
                } else if (isPlatoon) {
                    // infantry armour works differently
                    int armor = te.getArmor(hit);
                    int men = te.getInternal(hit);
                    tmpDamageHold = damage % 2;
                    damage /= 2;
                    if ((tmpDamageHold == 1) && (armor >= men)) {
                        // extra 1 point of damage to armor
                        tmpDamageHold = damage;
                        damage++;
                    } else {
                        // extra 0 or 1 point of damage to men
                        tmpDamageHold += damage;
                    }

                } else if (reflectiveArmor && (hit.getGeneralDamageType() == HitData.DAMAGE_PHYSICAL)) {
                    tmpDamageHold = damage;
                    damage *= 2;
                    r = new Report(6066);
                    r.subject = te_n;
                    r.indent(2);
                    r.newlines = 0;
                    r.add(damage);
                    vDesc.addElement(r);
                } else if (reflectiveArmor && (hit.getGeneralDamageType() == HitData.DAMAGE_ENERGY)) {
                    tmpDamageHold = damage;
                    damage = (int) Math.ceil(((double) damage) / 2);
                    r = new Report(6067);
                    r.subject = te_n;
                    r.indent(2);
                    r.newlines = 0;
                    r.add(damage);
                    vDesc.addElement(r);
                } else if (reactiveArmor && ( (hit.getGeneralDamageType() == HitData.DAMAGE_MISSILE) || (hit.getGeneralDamageType() == HitData.DAMAGE_ARMOR_PIERCING_MISSILE))) {
                    tmpDamageHold = damage;
                    damage = (int) Math.ceil(((double) damage) / 2);
                    r = new Report(6068);
                    r.subject = te_n;
                    r.indent(2);
                    r.newlines = 0;
                    r.add(damage);
                    vDesc.addElement(r);
                }

                if (te.getArmor(hit) >= damage) {

                    // armor absorbs all damage
                    te.setArmor(te.getArmor(hit) - damage, hit);
                    if (tmpDamageHold >= 0) {
                        te.damageThisPhase += tmpDamageHold;
                    } else {
                        te.damageThisPhase += damage;
                    }
                    damage = 0;
                    r = new Report(6085);
                    r.subject = te_n;
                    r.newlines = 0;
                    if (spotlightHittable) {
                        r.indent(3);
                    }
                    r.add(te.getArmor(hit));
                    vDesc.addElement(r);

                    // tele-missiles are destroyed if they lose all armor
                    if ((te instanceof TeleMissile) && (te.getArmor(hit) == damage)) {
                        vDesc.addAll(destroyEntity(te, "damage", false));
                    }

                } else {
                    // damage goes on to internal
                    int absorbed = Math.max(te.getArmor(hit), 0);
                    if (reflectiveArmor && (hit.getGeneralDamageType() == HitData.DAMAGE_PHYSICAL)) {
                        absorbed = (int) Math.round(Math.ceil(absorbed / 2));
                        damage = tmpDamageHold;
                        tmpDamageHold = 0;
                    }
                    te.setArmor(IArmorState.ARMOR_DESTROYED, hit);
                    if (tmpDamageHold >= 0) {
                        te.damageThisPhase += 2 * absorbed;
                    } else {
                        te.damageThisPhase += absorbed;
                    }
                    damage -= absorbed;
                    r = new Report(6090);
                    r.subject = te_n;
                    r.newlines = 0;
                    if (spotlightHittable) {
                        r.indent(3);
                    }
                    vDesc.addElement(r);
                    if (te instanceof GunEmplacement) {
                        // gun emplacements have no internal,
                        // destroy the section
                        te.destroyLocation(hit.getLocation());
                        r = new Report(6115);
                        r.subject = te_n;
                        r.newlines = 0;
                        vDesc.addElement(r);

                        if (te.getTransferLocation(hit).getLocation() == Entity.LOC_DESTROYED) {
                            vDesc.addAll(destroyEntity(te, "damage", false));
                        }
                    }
                }

                // targets with BAR armor get crits, depending on damage and BAR rating
                if (te.hasBARArmor()) {
                    if (origDamage > te.getBARRating()) {
                        if (te.hasArmoredChassis()) {
                            Report.addNewline(vDesc);
                            // crit roll with -1 mod
                            vDesc.addAll(criticalEntity(te, hit.getLocation(), -1));
                        } else {
                            Report.addNewline(vDesc);
                            vDesc.addAll(criticalEntity(te, hit.getLocation(), 0));
                        }
                    }
                }

                // If it has hardened armor, now we need to "correct" any
                // remaining damage.
                if (tmpDamageHold > 0) {
                    if (hardenedArmor) {
                        damage *= 2;
                        damage -= tmpDamageHold % 2;
                    } else if (isPlatoon) {
                        damage = tmpDamageHold;
                    }
                }
            }

            // is there damage remaining?
            if (damage > 0) {

                // if this is an Aero then I need to apply internal damage
                // to the SI after halving it. Return from here to prevent
                // further processing
                if (te instanceof Aero) {
                    Aero a = (Aero) te;

                    //check for overpenetration
                    if(game.getOptions().booleanOption("stratops_over_penetrate")) {
                        int opRoll = Compute.d6(1);
                        if((((te instanceof Jumpship) || (te instanceof SpaceStation)) && !(te instanceof Warship) && (opRoll > 3))
                                || ((te instanceof Dropship) && (opRoll > 4))
                                || ((te instanceof Warship) && (a.get0SI() <= 30) && (opRoll > 5))) {
                            //over-penetration happened
                            r = new Report(9090);
                            r.subject = te_n;
                            r.newlines = 0;
                            vDesc.addElement(r);
                            int new_loc = a.getOppositeLocation(hit.getLocation());
                            damage = Math.min(damage, te.getArmor(new_loc));
                            r = new Report(6065);
                            r.subject = te_n;
                            r.indent(2);
                            r.newlines = 0;
                            r.addDesc(te);
                            r.add(damage);
                            r.add(te.getLocationAbbr(new_loc));
                            vDesc.addElement(r);
                            te.setArmor(te.getArmor(new_loc) - damage, new_loc);
                            if((te instanceof Warship) || (te instanceof Jumpship)) {
                                damage = 1;
                            } else {
                                damage = 0;
                            }
                            //
                        }
                    }

                    // divide damage in half
                    // do not divide by half if it is an ammo exposion
                    if (!ammoExplosion && !nukeS2S) {
                        damage /= 2;
                    }

                    // this should result in a crit
                    // but only if it really did damage after rounding down
                    if (damage > 0) {
                        critSI = true;
                    }

                    // Now apply damage to the structural integrity
                    a.setSI(a.getSI() - damage);
                    te.damageThisPhase += damage;
                    // send the report
                    r = new Report(1210);
                    r.subject = te_n;
                    r.newlines = 0;
                    if (!ammoExplosion) {
                        r.messageId = 9005;
                    } else {
                        r.messageId = 9006;
                    }
                    r.add(damage);
                    r.add(Math.max(a.getSI(), 0));
                    vDesc.addElement(r);
                    damage = 0;
                    // check to see if this would destroy the ASF
                    if (a.getSI() <= 0) {
                        vDesc.addAll(destroyEntity(te, "structural integrity collapse"));
                        a.setSI(0);
                    }
                    checkAeroCrits(vDesc, a, hit, damage_orig, critThresh, critSI, ammoExplosion, nukeS2S);
                    return vDesc;
                }

                // Check for CASE II right away. if so reduce damage to 1
                // and let it hit the IS.
                // Also remove as much of the rear armor as allowed by the
                // damage. If arm/leg/head
                // Then they lose all their armor if its less then the
                // explosion damage.
                if (ammoExplosion && te.hasCASEII(hit.getLocation())) {
                    te.damageThisPhase += damage;
                    // 1 point of damage goes to IS
                    damage--;
                    // Remaining damage prevented by CASE II
                    r = new Report(6126);
                    r.subject = te_n;
                    r.add(damage);
                    r.indent(3);
                    r.newlines = 0;
                    vDesc.addElement(r);
                    boolean rearArmor = te.hasRearArmor(hit.getLocation());
                    if (damage > te.getArmor(hit.getLocation(), rearArmor)) {
                        te.setArmor(IArmorState.ARMOR_DESTROYED, hit.getLocation(), rearArmor);
                    } else {
                        te.setArmor(te.getArmor(hit.getLocation(), rearArmor) - damage, hit.getLocation(), rearArmor);
                    }

                    if (te.getInternal(hit) > 0) {
                        // Mek takes 1 point of IS damage
                        damage = 1;
                    } else {
                        damage = 0;
                    }

                    int roll = Compute.d6(2);
                    r = new Report(6127);
                    r.subject = te.getId();
                    r.add(roll);
                    r.newlines = 0;
                    vDesc.add(r);
                    if (roll >= 8) {
                        hit.setEffect(HitData.EFFECT_NO_CRITICALS);
                    }
                }
                // check for tank CASE here: damage to rear armor, excess
                // dissipating, and a crew stunned crit
                if (ammoExplosion && (te instanceof Tank) && te.locationHasCase(Tank.LOC_BODY)) {
                    te.damageThisPhase += damage;
                    r = new Report(6124);
                    r.subject = te_n;
                    r.indent(2);
                    r.add(damage);
                    vDesc.add(r);
                    if (damage > te.getArmor(Tank.LOC_REAR)) {
                        te.setArmor(IArmorState.ARMOR_DESTROYED, Tank.LOC_REAR);
                        r = new Report(6090);
                    } else {
                        te.setArmor(te.getArmor(Tank.LOC_REAR) - damage, Tank.LOC_REAR);
                        r = new Report(6085);
                        r.add(te.getArmor(Tank.LOC_REAR));
                    }
                    r.subject = te_n;
                    r.newlines = 0;
                    r.indent(2);
                    vDesc.add(r);
                    damage = 0;
                    int critIndex;
                    if (((Tank) te).isCommanderHit() && ((Tank) te).isDriverHit()) {
                        critIndex = Tank.CRIT_CREW_KILLED;
                    } else {
                        critIndex = Tank.CRIT_CREW_STUNNED;
                    }
                    vDesc.addAll(applyCriticalHit(te, Entity.NONE, new CriticalSlot(0, critIndex), true));
                }

                // is there internal structure in the location hit?
                if (te.getInternal(hit) > 0) {

                    // Now we need to consider alternate structure types!
                    int tmpDamageHold = -1;
                    if ((te instanceof Mech) && ((Mech) te).hasCompositeStructure()) {
                        tmpDamageHold = damage;
                        damage *= 2;
                    }
                    if ((te instanceof Mech) && ((Mech) te).hasReinforcedStructure()) {
                        tmpDamageHold = damage;
                        damage /= 2;
                        damage += tmpDamageHold % 2;
                    }
                    if ((te.getInternal(hit) > damage) && (damage > 0)) {
                        // internal structure absorbs all damage
                        te.setInternal(te.getInternal(hit) - damage, hit);
                        // Triggers a critical hit on Vehicles and Mechs.
                        if (!isPlatoon && !isBattleArmor) {
                            crits++;
                        }
                        tookInternalDamage = true;
                        te.damageThisPhase += damage;
                        damage = 0;
                        r = new Report(1210);
                        r.subject = te_n;
                        r.newlines = 0;
                        // Infantry platoons have men not "Internals".
                        if (isPlatoon) {
                            r.messageId = 6095;
                        } else {
                            r.messageId = 6100;
                        }
                        r.add(te.getInternal(hit));
                        vDesc.addElement(r);
                    } else if (damage > 0) {
                        // Triggers a critical hit on Vehicles and Mechs.
                        if (!isPlatoon && !isBattleArmor) {
                            crits++;
                        }
                        // damage transfers, maybe
                        int absorbed = Math.max(te.getInternal(hit), 0);

                        // Handle Protomech pilot damage
                        // due to location destruction
                        if (te instanceof Protomech) {
                            int hits = Protomech.POSSIBLE_PILOT_DAMAGE[hit.getLocation()] - ((Protomech) te).getPilotDamageTaken(hit.getLocation());
                            if (hits > 0) {
                                vDesc.addAll(damageCrew(te, hits));
                                ((Protomech) te).setPilotDamageTaken(hit.getLocation(), Protomech.POSSIBLE_PILOT_DAMAGE[hit.getLocation()]);
                            }
                        }

                        // Platoon, Trooper, or Section destroyed message
                        r = new Report(1210);
                        r.subject = te_n;
                        r.newlines = 0;
                        if (isPlatoon) {
                            // Infantry have only one section, and
                            // are therefore destroyed.
                            r.messageId = 6105;
                        } else if (isBattleArmor) {
                            r.messageId = 6110;
                        } else {
                            r.messageId = 6115;
                        }
                        vDesc.addElement(r);

                        // If a sidetorso got destroyed, and the
                        // corresponding arm is not yet destroyed, add
                        // it as a club to that hex (p.35 BMRr)
                        if ((te instanceof Mech) && (((hit.getLocation() == Mech.LOC_RT) && (te.getInternal(Mech.LOC_RARM) > 0)) || ((hit.getLocation() == Mech.LOC_LT) && (te.getInternal(Mech.LOC_LARM) > 0)))) {
                            int blownOffLocation = -1; // good initial value?
                            if (hit.getLocation() == Mech.LOC_RT) {
                                blownOffLocation = Mech.LOC_RARM;
                            } else {
                                blownOffLocation = Mech.LOC_LARM;
                            }
                            r = new Report(6120);
                            r.subject = te_n;
                            r.add(te.getLocationName(blownOffLocation));
                            r.newlines = 0;
                            vDesc.addElement(r);
                            IHex h = game.getBoard().getHex(te.getPosition());
                            if (te instanceof BipedMech) {
                                if (!h.containsTerrain(Terrains.ARMS)) {
                                    h.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.ARMS, 1));
                                } else {
                                    h.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.ARMS, h.terrainLevel(Terrains.ARMS) + 1));
                                }
                            } else if (!h.containsTerrain(Terrains.LEGS)) {
                                h.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.LEGS, 1));
                            } else {
                                h.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.LEGS, h.terrainLevel(Terrains.LEGS) + 1));
                            }
                            sendChangedHex(te.getPosition());
                        }

                        // Troopers riding on a location
                        // all die when the location is destroyed.
                        if ((te instanceof Mech) || (te instanceof Tank)) {
                            Entity passenger = te.getExteriorUnitAt(hit.getLocation(), hit.isRear());
                            if ((null != passenger) && !passenger.isDoomed()) {
                                HitData passHit = passenger.getTrooperAtLocation(hit, te);
                                // ensures a kill
                                passHit.setEffect(HitData.EFFECT_CRITICAL);
                                if (passenger.getInternal(passHit) > 0) {
                                    vDesc.addAll(damageEntity(passenger, passHit, damage));
                                }
                                passHit = new HitData(hit.getLocation(), !hit.isRear());
                                passHit = passenger.getTrooperAtLocation(passHit, te);
                                // ensures a kill
                                passHit.setEffect(HitData.EFFECT_CRITICAL);
                                if (passenger.getInternal(passHit) > 0) {
                                    vDesc.addAll(damageEntity(passenger, passHit, damage));
                                }
                            }
                        }
View Full Code Here

            r.newlines = 0;
            vDesc.addElement(r);

            while (damage > 0) {
                int cluster = Math.min(clusterAmt, damage);
                HitData hit = entity.rollHitLocation(ToHitData.HIT_NORMAL, Compute.targetSideTable(position, entity));
                vDesc.addAll(damageEntity(entity, hit, cluster, false, DamageType.IGNORE_PASSENGER, false, true));
                damage -= cluster;
            }
            Report.addNewline(vDesc);
        }

        // now deal with loaded units...
        for (Entity e : loaded) {
            // This can be null, if the transport died from damage
            final Entity transporter = game.getEntity(e.getTransportId());
            if ((transporter == null) || transporter.getExternalUnits().contains(e)) {
                // Its external or transport was destroyed - hit it.
                final Coords entityPos = (transporter == null ? e.getPosition() : transporter.getPosition());
                final int range = position.distance(entityPos);

                if (range >= damages.length) {
                    // Yeah, this is fine. It's outside the blast radius.
                    continue;
                }

                int damage = damages[range];
                if (allowShelter) {
                    final int absHeight = (transporter == null ? e.absHeight() : transporter.absHeight());
                    if ((entityPos != null) && canShelter(entityPos, position, absHeight)) {
                        if (isSheltered()) {
                            r = new Report(6545);
                            r.addDesc(e);
                            r.subject = e.getId();
                            vDesc.addElement(r);
                            continue;
                        }
                        // If shelter is allowed but didn't work, report that.
                        r = new Report(6546);
                        r.subject = e.getId();
                        r.addDesc(e);
                        vDesc.addElement(r);
                    }
                }
                // No shelter
                // Since it's taking damage, add it to the list of units hit.
                vUnits.add(e.getId());

                r = new Report(6175);
                r.subject = e.getId();
                r.indent(2);
                r.addDesc(e);
                r.add(damage);
                r.newlines = 0;
                vDesc.addElement(r);

                while (damage > 0) {
                    int cluster = Math.min(5, damage);
                    HitData hit = e.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
                    vDesc.addAll(damageEntity(e, hit, cluster, false, DamageType.IGNORE_PASSENGER, false, true));
                    damage -= cluster;
                }
                Report.addNewline(vDesc);
            }
View Full Code Here

                // Standard infantry are auto-killed in this band, unless
                // they're in a building.
                if (game.getBoard().getHex(entity.getPosition()).containsTerrain(Terrains.BUILDING)) {
                    // 50% casualties, rounded up.
                    int damage = (int) (Math.ceil((((Infantry) entity).getInternal(Infantry.LOC_INFANTRY)) / 2.0));
                    vDesc.addAll(damageEntity(entity, new HitData(Infantry.LOC_INFANTRY), damage, true));
                } else {
                    vDesc.addAll(destroyEntity(entity, "nuclear explosion secondary effects", false, false));
                    entity.getCrew().setDoomed(true);
                }
            } else if (entity instanceof Tank) {
                // All vehicles suffer two critical hits...
                HitData hd = entity.rollHitLocation(ToHitData.HIT_NORMAL, entity.sideTable(position));
                vDesc.addAll(oneCriticalEntity(entity, hd.getLocation()));
                hd = entity.rollHitLocation(ToHitData.HIT_NORMAL, entity.sideTable(position));
                vDesc.addAll(oneCriticalEntity(entity, hd.getLocation()));

                // ...and a Crew Killed hit.
                vDesc.addAll(applyCriticalHit(entity, 0, new CriticalSlot(0, Tank.CRIT_CREW_KILLED), false));
            } else if ((entity instanceof Mech) || (entity instanceof Protomech)) {
                // 'Mechs suffer two critical hits...
                HitData hd = entity.rollHitLocation(ToHitData.HIT_NORMAL, entity.sideTable(position));
                vDesc.addAll(oneCriticalEntity(entity, hd.getLocation()));
                hd = entity.rollHitLocation(ToHitData.HIT_NORMAL, entity.sideTable(position));
                vDesc.addAll(oneCriticalEntity(entity, hd.getLocation()));

                // and four pilot hits.
                vDesc.addAll(damageCrew(entity, 4));
            } else {
                // Buildings and gun emplacements and such are only effected by
                // the EMI.
                // No auto-crits or anything.
            }
        } else if (roll <= 10) {
            if (entity instanceof BattleArmor) {
                // It takes 25% casualties, rounded up.
                BattleArmor myBA = (BattleArmor) entity;
                int numDeaths = (int) (Math.ceil(((myBA.getNumberActiverTroopers())) / 4.0));
                for (int x = 0; x < numDeaths; x++) {
                    vDesc.addAll(applyCriticalHit(entity, 0, null, false));
                }
            } else if (entity instanceof Infantry) {
                if (game.getBoard().getHex(entity.getPosition()).containsTerrain(Terrains.BUILDING)) {
                    // 25% casualties, rounded up.
                    int damage = (int) (Math.ceil((((Infantry) entity).getInternal(Infantry.LOC_INFANTRY)) / 4.0));
                    vDesc.addAll(damageEntity(entity, new HitData(Infantry.LOC_INFANTRY), damage, true));
                } else {
                    // 50% casualties, rounded up.
                    int damage = (int) (Math.ceil((((Infantry) entity).getInternal(Infantry.LOC_INFANTRY)) / 2.0));
                    vDesc.addAll(damageEntity(entity, new HitData(Infantry.LOC_INFANTRY), damage, true));
                }
            } else if (entity instanceof Tank) {
                // It takes one crit...
                HitData hd = entity.rollHitLocation(ToHitData.HIT_NORMAL, entity.sideTable(position));
                vDesc.addAll(oneCriticalEntity(entity, hd.getLocation()));

                // Plus a Crew Stunned critical.
                vDesc.addAll(applyCriticalHit(entity, 0, new CriticalSlot(0, Tank.CRIT_CREW_STUNNED), false));
            } else if ((entity instanceof Mech) || (entity instanceof Protomech)) {
                // 'Mechs suffer a critical hit...
                HitData hd = entity.rollHitLocation(ToHitData.HIT_NORMAL, entity.sideTable(position));
                vDesc.addAll(oneCriticalEntity(entity, hd.getLocation()));

                // and two pilot hits.
                vDesc.addAll(damageCrew(entity, 2));
            } else {
                // Buildings and gun emplacements and such are only effected by
View Full Code Here

        Report r;

        // Handle hits on "critical slots" of tanks.
        if (en instanceof Tank) {
            Tank t = (Tank) en;
            HitData hit;
            switch (cs.getIndex()) {
            case Tank.CRIT_NONE:
                // no effect
                r = new Report(6005);
                r.subject = t.getId();
                vDesc.add(r);
                break;
            case Tank.CRIT_AMMO:
                // ammo explosion
                r = new Report(6610);
                r.subject = t.getId();
                vDesc.add(r);
                int damage = 0;
                for (Mounted m : t.getAmmo()) {
                    m.setHit(true);
                    int tmp = m.getShotsLeft() * ((AmmoType) m.getType()).getDamagePerShot() * ((AmmoType) m.getType()).getRackSize();
                    m.setShotsLeft(0);
                    // non-explosive ammo can't explode
                    if (!m.getType().isExplosive()) {
                        continue;
                    }
                    damage += tmp;
                    r = new Report(6390);
                    r.subject = t.getId();
                    r.add(m.getName());
                    r.add(tmp);
                    r.newlines = 0;
                    vDesc.add(r);
                }
                hit = new HitData(loc);
                vDesc.addAll(damageEntity(t, hit, damage, true));
                break;
            case Tank.CRIT_CARGO:
                // Cargo/infantry damage
                r = new Report(6615);
View Full Code Here

            boolean exploded = false;

            // standard damage loop
            while (damage > 0) {
                int cluster = Math.min(5, damage);
                HitData hit = en.rollHitLocation(ToHitData.HIT_NORMAL, table);
                hit.setGeneralDamageType(HitData.DAMAGE_PHYSICAL);
                int ISBefore[] = { en.getInternal(Tank.LOC_FRONT), en.getInternal(Tank.LOC_RIGHT), en.getInternal(Tank.LOC_LEFT), en.getInternal(Tank.LOC_REAR) };// hack?
                vDesc.addAll(damageEntity(en, hit, cluster));
                int ISAfter[] = { en.getInternal(Tank.LOC_FRONT), en.getInternal(Tank.LOC_RIGHT), en.getInternal(Tank.LOC_LEFT), en.getInternal(Tank.LOC_REAR) };
                for (int x = 0; x <= 3; x++) {
                    if (ISBefore[x] != ISAfter[x]) {
                        exploded = true;
                    }
                }
                damage -= cluster;
            }
            if (exploded) {
                r = new Report(6285);
                r.subject = en.getId();
                r.addDesc(en);
                vDesc.addElement(r);
                vDesc.addAll(explodeVTOLorWiGE(en));
            }

            // check for location exposure
            vDesc.addAll(doSetLocationsExposure(en, fallHex, false, newElevation));

        } else {
            en.setElevation(0);// considered landed in the hex.
            // crashes into ground thanks to sideslip
            r = new Report(6290);
            r.subject = en.getId();
            r.addDesc(en);
            vDesc.addElement(r);
            int damage = (int) Math.round(en.getWeight() / 10.0) * (hexesMoved + 1);
            boolean exploded = false;

            // standard damage loop
            while (damage > 0) {
                int cluster = Math.min(5, damage);
                HitData hit = en.rollHitLocation(ToHitData.HIT_NORMAL, impactSide);
                hit.setGeneralDamageType(HitData.DAMAGE_PHYSICAL);
                int ISBefore[] = { en.getInternal(Tank.LOC_FRONT), en.getInternal(Tank.LOC_RIGHT), en.getInternal(Tank.LOC_LEFT), en.getInternal(Tank.LOC_REAR) };// hack?
                vDesc.addAll(damageEntity(en, hit, cluster));
                int ISAfter[] = { en.getInternal(Tank.LOC_FRONT), en.getInternal(Tank.LOC_RIGHT), en.getInternal(Tank.LOC_LEFT), en.getInternal(Tank.LOC_REAR) };
                for (int x = 0; x <= 3; x++) {
                    if (ISBefore[x] != ISAfter[x]) {
View Full Code Here

                            r.subject = en.getId();
                            r.indent(3);
                            r.newlines = 0;
                            vDesc.addElement(r);
                            vDesc.addElement(r);
                            vDesc.addAll(damageEntity(en, new HitData(loc), en.getArmor(loc)));
                            if (en.hasRearArmor(loc)) {
                                vDesc.addAll(damageEntity(en, new HitData(loc, true), en.getArmor(loc, true)));
                            }
                            vDesc.addAll(damageEntity(en, new HitData(loc), 1));
                        } else {
                            continue;
                        }
                    }
                }
View Full Code Here

                r.indent(2);
                vDesc.addElement(r);
            }
        }

        HitData hit = new HitData(loc);
        // check to determine whether this is capital scale if we have a capital
        // scale entity
        if (mounted.getType() instanceof AmmoType) {
            if (((AmmoType) mounted.getType()).isCapital()) {
                hit.setCapital(true);
            }

        }

        mounted.setShotsLeft(0);
View Full Code Here

TOP

Related Classes of megamek.common.HitData

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.