throw new IllegalArgumentException("Tanks shouldnt be here");
Tank t = (Tank)en; HitData hit; switch(cs.getIndex()) { case Tank.CRIT_NONE:  r = new Report(6005); r.subject = t.getId(); vDesc.add(r); break; case Tank.CRIT_AMMO:  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(); 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:  r = new Report(6615); r.subject = t.getId(); vDesc.add(r); Vector<Entity> passengers = t.getLoadedUnits(); Entity target = passengers.get(Compute.randomInt(passengers.size())); hit = target.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT); vDesc.addAll(damageEntity(t, hit, 10)); break; case Tank.CRIT_COMMANDER: r = new Report(6600); r.subject = t.getId(); vDesc.add(r); t.setCommanderHit(true); break; case Tank.CRIT_DRIVER: r = new Report(6605); r.subject = t.getId(); vDesc.add(r); t.setCommanderHit(true); break; case Tank.CRIT_CREW_KILLED: r = new Report(6190); r.subject = t.getId(); vDesc.add(r); t.getCrew().setDoomed(true); break; case Tank.CRIT_CREW_STUNNED: t.stunCrew(); r = new Report(6185); r.add(t.getStunnedTurns() - 1); r.subject = t.getId(); vDesc.add(r); break; case Tank.CRIT_ENGINE: r = new Report(6210); r.subject = t.getId(); vDesc.add(r); t.immobilize(); t.lockTurret(); for(Mounted m:t.getWeaponList()) { WeaponType wtype = (WeaponType)m.getType(); if(wtype.hasFlag(WeaponType.F_ENERGY)) m.setBreached(true); } if(t instanceof VTOL) { PilotingRollData psr = t.getBasePilotingRoll(); IHex hex = game.getBoard().getHex(t.getPosition()); psr.addModifier(4, "forced landing"); int elevation = Math.max(hex.terrainLevel(Terrains.BLDG_ELEV), hex.terrainLevel(Terrains.BRIDGE_ELEV)); elevation = Math.max(elevation,0); elevation = Math.min(elevation, t.getElevation()); if(t.getElevation() > elevation) { if(!hex.containsTerrain(Terrains.FUEL_TANK) && !hex.containsTerrain(Terrains.JUNGLE) && !hex.containsTerrain(Terrains.MAGMA) && !hex.containsTerrain(Terrains.MUD) && !hex.containsTerrain(Terrains.RUBBLE) && !hex.containsTerrain(Terrains.WATER) && !hex.containsTerrain(Terrains.WOODS)) { r = new Report(2180); r.subject = t.getId(); r.addDesc(t); r.add(psr.getLastPlainDesc(), true); vDesc.add(r);   final int diceRoll = Compute.d6(2); r = new Report(2185); r.subject = t.getId(); r.add(psr.getValueAsString()); r.add(psr.getDesc()); r.add(diceRoll); if (diceRoll < psr.getValue()) { r.choose(false); vDesc.add(r); vDesc.addAll(crashVTOL((VTOL)t)); } else { r.choose(true); vDesc.add(r); t.setElevation(elevation); } } else { vDesc.addAll(crashVTOL((VTOL)t)); } } } break; case Tank.CRIT_FUEL_TANK: r = new Report(6215); r.subject = t.getId(); vDesc.add(r); vDesc.addAll(destroyEntity(t, "fuel explosion", false, false)); break; case Tank.CRIT_SENSOR: r = new Report(6620); r.subject = t.getId(); vDesc.add(r); t.setSensorHits(t.getSensorHits() + 1); break; case Tank.CRIT_STABILIZER: r = new Report(6625); r.subject = t.getId(); vDesc.add(r); t.setStabiliserHit(loc); break; case Tank.CRIT_TURRET_DESTROYED: r = new Report(6630); r.subject = t.getId(); vDesc.add(r); destroyLocation(t,Tank.LOC_TURRET); break; case Tank.CRIT_TURRET_JAM:  r = new Report(6635); r.subject = t.getId(); vDesc.add(r); t.lockTurret(); break; case Tank.CRIT_TURRET_LOCK: r = new Report(6640); r.subject = t.getId(); vDesc.add(r); t.lockTurret(); break; case Tank.CRIT_WEAPON_DESTROYED: { r = new Report(6305); r.subject = t.getId(); ArrayList<Mounted> weapons = new ArrayList<Mounted>(); for(Mounted weap: t.getWeaponList()) { if(weap.getLocation() == loc) { weapons.add(weap); } } Mounted weapon = weapons.get(Compute.randomInt(weapons.size())); weapon.setHit(true); weapon.setDestroyed(true); r.add(weapon.getName()); vDesc.add(r); break; } case Tank.CRIT_WEAPON_JAM: { r = new Report(6645); r.subject = t.getId(); ArrayList<Mounted> weapons = new ArrayList<Mounted>(); for(Mounted weap: t.getWeaponList()) { if(weap.getLocation() == loc) { weapons.add(weap); } } Mounted weapon = weapons.get(Compute.randomInt(weapons.size())); weapon.setJammed(true); r.add(weapon.getName()); vDesc.add(r); break; } case VTOL.CRIT_PILOT: r = new Report(6650); r.subject = t.getId(); vDesc.add(r); t.setDriverHit(true); PilotingRollData psr = t.getBasePilotingRoll(); psr.addModifier(0, "pilot injury"); if(!doSkillCheckInPlace(t, psr)) { r = new Report(6675); r.subject = t.getId(); r.addDesc(t); vDesc.add(r); boolean crash = true; if(t.canGoDown()) { t.setElevation(t.getElevation() - 1); crash = !t.canGoDown(); } if(crash) { vDesc.addAll(crashVTOL((VTOL)t)); } } break; case VTOL.CRIT_COPILOT: r = new Report(6655); r.subject = t.getId(); vDesc.add(r); t.setCommanderHit(true); break; case VTOL.CRIT_ROTOR_DAMAGE: { r = new Report(6660); r.subject = t.getId(); vDesc.add(r); int mp = t.getOriginalWalkMP(); if(mp > 1) t.setOriginalWalkMP(mp - 1); else if (mp==1) { t.setOriginalWalkMP(0); vDesc.addAll(crashVTOL((VTOL)t)); } break; } case VTOL.CRIT_ROTOR_DESTROYED: r = new Report(6670); r.subject = t.getId(); vDesc.add(r); t.immobilize(); destroyLocation(t,VTOL.LOC_ROTOR); vDesc.addAll(crashVTOL((VTOL)t)); break; case VTOL.CRIT_FLIGHT_STABILIZER: r = new Report(6665); r.subject = t.getId(); vDesc.add(r); t.setStabiliserHit(VTOL.LOC_ROTOR); break; }
    public Vector applyCriticalHit( Entity en, int loc, CriticalSlot cs,                                     boolean secondaryEffects ) {        Vector vDesc = new Vector();        Report r;        // Handle hits on "critical slots" of tanks.        if( en instanceof Tank ) {            throw new IllegalArgumentException("Tanks shouldnt be here");        }        if (en instanceof BattleArmor) {            // We might as well handle this here.            // However, we're considering a crit against BA as a "crew kill".            BattleArmor ba = (BattleArmor)en;            r = new Report(6111);            int randomTrooper = ba.getRandomTrooper();            destroyLocation(ba, randomTrooper);            r.add(randomTrooper);            r.newlines = 1;            vDesc.add(r);        } else if ( CriticalSlot.TYPE_SYSTEM == cs.getType() ) {            // Handle critical hits on system slots.            cs.setHit(true);            if (en instanceof Protomech) {                int numHit=((Protomech)en).getCritsHit(loc);                if ( cs.getIndex() != Protomech.SYSTEM_TORSO_WEAPON_A &&                     cs.getIndex() != Protomech.SYSTEM_TORSO_WEAPON_B ) {                    r = new Report(6225);                    r.subject = en.getId();                    r.indent(3);                    r.newlines = 0;                    r.add(Protomech.systemNames[cs.getIndex()]);                    vDesc.addElement(r);                }                switch (cs.getIndex()) {                case Protomech.SYSTEM_HEADCRIT:                    if (2==numHit) {                        r = new Report(6230);                        r.subject = en.getId();                        r.newlines = 0;                        vDesc.addElement(r);                        destroyLocation(en, loc);                    }                    break;                case Protomech.SYSTEM_ARMCRIT:                    if (2==numHit) {                        r = new Report(6235);                        r.subject = en.getId();                        r.newlines = 0;                        vDesc.addElement(r);                        destroyLocation(en,loc);                    }                    break;                case Protomech.SYSTEM_LEGCRIT:                    if (3==numHit) {                        r = new Report(6240);                        r.subject = en.getId();                        r.newlines = 0;                        vDesc.addElement(r);                        destroyLocation(en,loc);                    }                    break;                case Protomech.SYSTEM_TORSOCRIT:                    if (3==numHit) {                        vDesc.addAll(                            destroyEntity(en, "torso destruction"));                    }                    // Torso weapon hits are secondary effects and                    // do not occur when loading from a scenario.                    else if ( secondaryEffects ) {                        int tweapRoll=Compute.d6(1);                        CriticalSlot newSlot = null;                        switch (tweapRoll) {                        case 1:                        case 2:                            newSlot = new CriticalSlot                                ( CriticalSlot.TYPE_SYSTEM,                                  Protomech.SYSTEM_TORSO_WEAPON_A );                            vDesc.addAll(                                applyCriticalHit(en, Entity.NONE,                                                  newSlot, secondaryEffects));                            break;                        case 3:                        case 4:                            newSlot = new CriticalSlot                                ( CriticalSlot.TYPE_SYSTEM,                                  Protomech.SYSTEM_TORSO_WEAPON_B );                            vDesc.addAll(                                applyCriticalHit(en, Entity.NONE,                                                  newSlot, secondaryEffects));                            break;                        case 5:                        case 6:                            //no effect                        }                    }                    break;                case Protomech.SYSTEM_TORSO_WEAPON_A:                    Mounted weaponA =( (Protomech) en ).getTorsoWeapon(true);                    if ( null != weaponA ) {                        weaponA.setHit(true);                        r = new Report(6245);                        r.subject = en.getId();                        r.newlines = 0;                        vDesc.addElement(r);                    }                    break;                case Protomech.SYSTEM_TORSO_WEAPON_B:                    Mounted weaponB = ( (Protomech) en ).getTorsoWeapon(false);                    if ( null != weaponB ) {                        weaponB.setHit(true);                        r = new Report(6250);                        r.subject = en.getId();                        r.newlines = 0;                        vDesc.addElement(r);                    }                    break;                } // End switch( cs.getType() )                // Shaded hits cause pilot damage.                if ( ((Protomech)en).shaded(loc, numHit) ) {                    // Destroyed Protomech sections have                    // already damaged the pilot.                    int pHits =                        Protomech.POSSIBLE_PILOT_DAMAGE[ loc ] -                        ((Protomech)en).getPilotDamageTaken( loc );                    if (  Math.min(1, pHits) > 0 ) {                        Report.addNewline(vDesc);                        vDesc.addAll(                                              damageCrew(en, 1));                        pHits = 1 + ((Protomech)en)                            .getPilotDamageTaken( loc );                        ((Protomech)en).setPilotDamageTaken                            ( loc, pHits );                    }                } // End have-shaded-hit            } // End entity-is-protomech            else {                r = new Report(6225);                r.subject = en.getId();                r.indent(3);                r.add(((Mech)en).getSystemName(cs.getIndex()));                r.newlines = 0;                vDesc.addElement(r);                switch(cs.getIndex()) {                case Mech.SYSTEM_COCKPIT :                    // Don't kill a pilot multiple times.                    if ( Pilot.DEATH > en.getCrew().getHits() ) {                        // boink!                        en.getCrew().setDoomed(true);                        Report.addNewline(vDesc);                        vDesc.addAll(                            destroyEntity(en, "pilot death", true));                    }                    break;                case Mech.SYSTEM_ENGINE :                    en.engineHitsThisRound++;                    boolean engineExploded = false;                    int numEngineHits = 0;                    numEngineHits += en.getHitCriticals                        (CriticalSlot.TYPE_SYSTEM,                         Mech.SYSTEM_ENGINE, Mech.LOC_CT);                    numEngineHits += en.getHitCriticals                        (CriticalSlot.TYPE_SYSTEM,                         Mech.SYSTEM_ENGINE, Mech.LOC_RT);                    numEngineHits += en.getHitCriticals                        (CriticalSlot.TYPE_SYSTEM,                         Mech.SYSTEM_ENGINE, Mech.LOC_LT);                    engineExploded = checkEngineExplosion(en, vDesc, numEngineHits);                    if ( !engineExploded && numEngineHits > 2 ) {                        // third engine hit                        vDesc.addAll(                            destroyEntity(en, "engine destruction"));                        if (game.getOptions().booleanOption("auto_abandon_unit")) {                            vDesc.addAll(abandonEntity(en));                        }                    }                    break;                case Mech.SYSTEM_GYRO :                    if ( en.getGyroType() != Mech.GYRO_HEAVY_DUTY ){                        if (en.getHitCriticals(CriticalSlot.TYPE_SYSTEM,                                               Mech.SYSTEM_GYRO, loc) > 1) {                                    // gyro destroyed                            game.addPSR( new PilotingRollData                                (en.getId(), PilotingRollData.AUTOMATIC_FAIL,                                 3, "gyro destroyed") );                        } else {                                    // first gyro hit                            game.addPSR( new PilotingRollData                                (en.getId(), 3, "gyro hit") );                        }//No check against HD Gyros.                    }else{                        int gyroHits = en.getHitCriticals(CriticalSlot.TYPE_SYSTEM,Mech.SYSTEM_GYRO, loc);                        if ( gyroHits > 2) {                            // gyro destroyed                            game.addPSR( new PilotingRollData (en.getId(), PilotingRollData.AUTOMATIC_FAIL,                              3, "gyro destroyed") );                        } else if ( gyroHits == 1 ){                            //first gyro hit                            game.addPSR( new PilotingRollData                                (en.getId(), 2, "gyro hit") );                        } else {                            // second gyro hit                            game.addPSR( new PilotingRollData                                (en.getId(), 3, "gyro hit") );                        }                    }                    break;                case Mech.ACTUATOR_UPPER_LEG :                case Mech.ACTUATOR_LOWER_LEG :                case Mech.ACTUATOR_FOOT :                    // leg/foot actuator piloting roll                    game.addPSR( new PilotingRollData                        (en.getId(), 1, "leg/foot actuator hit") );                    break;                case Mech.ACTUATOR_HIP :                    // hip piloting roll                    game.addPSR( new PilotingRollData                        (en.getId(), 2, "hip actuator hit") );                    break;                }            } // End entity-is-mek        } // End crit-on-system-slot        // Handle critical hits on equipment slots.        else if ( CriticalSlot.TYPE_EQUIPMENT == cs.getType() ) {            cs.setHit(true);            Mounted mounted = en.getEquipment(cs.getIndex());            EquipmentType eqType = mounted.getType();            boolean hitBefore = mounted.isHit();            r = new Report(6225);            r.subject = en.getId();            r.indent(3);            r.add(mounted.getDesc());            r.newlines = 0;            vDesc.addElement(r);            //Shield objects are not useless when they take one crit.            //Shields can be critted and still be usable.            if (eqType instanceof MiscType && ((MiscType)eqType).isShield())                mounted.setHit(false);            else                mounted.setHit(true);            if (eqType instanceof MiscType && eqType.hasFlag(MiscType.F_HARJEL)) {                r = new Report(6254);                r.subject = en.getId();                r.indent(2);                breachLocation(en, loc, null, true);            }            // If the item is the ECM suite of a Mek Stealth system            // then it's destruction turns off the stealth.            if ( !hitBefore && eqType instanceof MiscType &&                 eqType.hasFlag(MiscType.F_ECM) &&                 mounted.getLinkedBy() != null ) {                Mounted stealth = mounted.getLinkedBy();                r = new Report(6255);                r.subject = en.getId();                r.indent(2);                r.add(stealth.getType().getName());                r.newlines = 0;                vDesc.addElement(r);                stealth.setMode( "Off" );            }            // Handle equipment explosions.            // Equipment explosions are secondary effects and            // do not occur when loading from a scenario.            if ( (secondaryEffects && eqType.isExplosive() || mounted.isHotLoaded()) && !hitBefore ) {                vDesc.addAll(explodeEquipment(en, loc, mounted));            }            // Make sure that ammo in this slot is exhaused.            if ( mounted.getShotsLeft() > 0 ) {                mounted.setShotsLeft(0);            }        } // End crit-on-equipment-slot        // mechs with TSM hit by anti-tsm missiles this round get another crit        if (en instanceof Mech && en.hitThisRoundByAntiTSM) {            Mech mech = (Mech)en;            if (mech.hasTSM()) {                r = new Report(6430);                r.subject = en.getId();                r.indent(2);                r.addDesc(en);                r.newlines = 0;                vDesc.addElement(r);                vDesc.addAll(oneCriticalEntity(en, Compute.d6(2)));            }            en.hitThisRoundByAntiTSM = false;        }        // Return the results of the damage.        return vDesc;    }