/**
* Handle a kick attack
*/
private void resolveKickAttack(PhysicalResult pr, int lastEntityId) {
KickAttackAction kaa = (KickAttackAction) pr.aaa;
final Entity ae = game.getEntity(kaa.getEntityId());
final Targetable target = game.getTarget(kaa.getTargetType(), kaa.getTargetId());
Entity te = null;
if (target.getTargetType() == Targetable.TYPE_ENTITY) {
te = (Entity) target;
}
boolean throughFront = true;
if (te != null) {
throughFront = Compute.isThroughFrontHex(game, ae.getPosition(), te);
}
String legName = (kaa.getLeg() == KickAttackAction.LEFT) || (kaa.getLeg() == KickAttackAction.LEFTMULE) ? "Left " : "Right ";
if ((kaa.getLeg() == KickAttackAction.LEFTMULE) || (kaa.getLeg() == KickAttackAction.RIGHTMULE)) {
legName.concat(" rear ");
} else {
legName.concat(" front ");
}
legName.concat("leg");
Report r;
// get damage, ToHitData and roll from the PhysicalResult
int damage = pr.damage;
final ToHitData toHit = pr.toHit;
int roll = pr.roll;
final boolean targetInBuilding = Compute.isInBuilding(game, te);
final boolean glancing = game.getOptions().booleanOption("tacops_glancing_blows") && (roll == toHit.getValue());
// Set Margin of Success/Failure.
toHit.setMoS(roll - Math.max(2, toHit.getValue()));
final boolean directBlow = game.getOptions().booleanOption("tacops_direct_blow") && ((toHit.getMoS() / 3) >= 1);
// Which building takes the damage?
Building bldg = game.getBoard().getBuildingAt(target.getPosition());
if (lastEntityId != ae.getId()) {
// who is making the attacks
r = new Report(4005);
r.subject = ae.getId();
r.addDesc(ae);
addReport(r);
}
r = new Report(4055);
r.subject = ae.getId();
r.indent();
r.add(legName);
r.add(target.getDisplayName());
r.newlines = 0;
addReport(r);
if (toHit.getValue() == TargetRoll.IMPOSSIBLE) {
r = new Report(4060);
r.subject = ae.getId();
r.add(toHit.getDesc());
addReport(r);
game.addPSR(new PilotingRollData(ae.getId(), 0, "missed a kick"));
return;
} else if (toHit.getValue() == TargetRoll.AUTOMATIC_SUCCESS) {
r = new Report(4065);
r.subject = ae.getId();
r.add(toHit.getDesc());
r.newlines = 0;
addReport(r);
roll = Integer.MAX_VALUE;
} else {
r = new Report(4025);
r.subject = ae.getId();
r.add(toHit.getValue());
r.add(roll);
r.newlines = 0;
addReport(r);
if (glancing) {
r = new Report(4030);
r.subject = ae.getId();
r.newlines = 0;
addReport(r);
}
if (directBlow) {
r = new Report(4032);
r.subject = ae.getId();
r.newlines = 0;
addReport(r);
}
}
// do we hit?
if (roll < toHit.getValue()) {
// miss
r = new Report(4035);
r.subject = ae.getId();
addReport(r);
game.addPSR(new PilotingRollData(ae.getId(), 0, "missed a kick"));
// If the target is in a building, the building absorbs the damage.
if (targetInBuilding && (bldg != null)) {
// Only report if damage was done to the building.
if (damage > 0) {
Vector<Report> buildingReport = damageBuilding(bldg, damage, target.getPosition());
for (Report report : buildingReport) {
report.subject = ae.getId();
}
addReport(buildingReport);
}
}
return;
}
// Targeting a building.
if ((target.getTargetType() == Targetable.TYPE_BUILDING) || (target.getTargetType() == Targetable.TYPE_FUEL_TANK)) {
// The building takes the full brunt of the attack.
r = new Report(4040);
r.subject = ae.getId();
addReport(r);
Vector<Report> buildingReport = damageBuilding(bldg, damage, target.getPosition());
for (Report report : buildingReport) {
report.subject = ae.getId();
}
addReport(buildingReport);
// Damage any infantry in the hex.
damageInfantryIn(bldg, damage, target.getPosition());
// And we're done!
return;
}
HitData hit = te.rollHitLocation(toHit.getHitTable(), toHit.getSideTable());
hit.setGeneralDamageType(HitData.DAMAGE_PHYSICAL);
r = new Report(4045);
r.subject = ae.getId();
r.add(toHit.getTableDesc());
r.add(te.getLocationAbbr(hit));
r.newlines = 0;
addReport(r);
// The building shields all units from a certain amount of damage.
// The amount is based upon the building's CF at the phase's start.
if (targetInBuilding && (bldg != null)) {
int bldgAbsorbs = (int) Math.ceil(bldg.getPhaseCF(target.getPosition()) / 10.0);
int toBldg = Math.min(bldgAbsorbs, damage);
damage -= toBldg;
addNewLines();
Vector<Report> buildingReport = damageBuilding(bldg, damage, target.getPosition());
for (Report report : buildingReport) {
report.subject = ae.getId();
}
addReport(buildingReport);
}
// A building may absorb the entire shot.
if (damage == 0) {
r = new Report(4050);
r.subject = ae.getId();
r.add(te.getShortName());
r.add(te.getOwner().getName());
r.newlines = 0;
addReport(r);
} else {
if (glancing) {
damage = (int) Math.floor(damage / 2.0);
}
if (directBlow) {
damage += toHit.getMoS() / 3;
hit.makeDirectBlow(toHit.getMoS() / 3);
}
if ((damage >= 1) && te.hasWorkingMisc(MiscType.F_SPIKES, -1, hit.getLocation())) {
r = new Report(4330);
r.indent(2);
r.newlines = 0;
r.subject = ae.getId();
addReport(r);
checkBreakSpikes(te, hit.getLocation());
damage = Math.max(1, damage - 4);
HitData ahit;
switch (kaa.getLeg()) {
case KickAttackAction.LEFT:
if (ae instanceof QuadMech) {
ahit = new HitData(Mech.LOC_LARM);
} else {
ahit = new HitData(Mech.LOC_LLEG);