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));
}
}
}