4.0, 4.49, 4.98, 5.47, 6.31, 7.23, 8.14, 8.59, 9.04, 9.5, 10.1,
10.8, 11.42, 12.1, 12.7 };
boolean use_table = false;
Infantry inf_attacker = new Infantry();
BattleArmor ba_attacker = new BattleArmor();
Mounted lnk_guide;
if (attacker instanceof BattleArmor) {
ba_attacker = (BattleArmor) attacker;
}
if ((attacker instanceof Infantry)
&& !(attacker instanceof BattleArmor)) {
inf_attacker = (Infantry) attacker;
}
// Only infantry can fire into their own hex
if (!(attacker instanceof Infantry) & (range == 0)) {
return 0.0;
}
double fDamage = 0.0;
WeaponType wt = (WeaponType) weapon.getType();
// The "Stop Swarm Attack" really isn't one
if (wt.getName() == "Stop Swarm Attack") {
return 0.0;
}
// Get the range modifier for the weapon
if (range <= wt.getMinimumRange()) {
total_mod = total_mod + 1 + (wt.getMinimumRange() - range);
} else {
if (range > wt.getShortRange()) {
total_mod += 2;
}
if (range > wt.getMediumRange()) {
total_mod += 2;
}
if (range > wt.getLongRange()) {
total_mod += 4;
}
if (range > wt.getExtremeRange()) {
return 0.0;
}
}
// Get the weapon to-hit mod
total_mod += wt.getToHitModifier();
// Some weapons use multiple hits, as determined by the missile
// hits table. This method is used for an approximation, so
// assume LBX cannon are using cluster rounds, Ultra-cannon
// are firing double rate, and RACs are fired in quad mode.
if ((wt.getDamage() == WeaponType.DAMAGE_MISSILE)
&& ((wt.getAmmoType() != AmmoType.T_TBOLT_5) ||
(wt.getAmmoType() != AmmoType.T_TBOLT_10) ||
(wt.getAmmoType() != AmmoType.T_TBOLT_15) ||
(wt.getAmmoType() != AmmoType.T_TBOLT_20))) {
use_table = true;
}
if ((wt.getAmmoType() == AmmoType.T_AC_LBX)
|| (wt.getAmmoType() == AmmoType.T_AC_LBX_THB)) {
use_table = true;
total_mod -= 1;
}
if ((wt.getAmmoType() == AmmoType.T_AC_ULTRA)
|| (wt.getAmmoType() == AmmoType.T_AC_ULTRA_THB)
|| (wt.getAmmoType() == AmmoType.T_AC_ROTARY)) {
use_table = true;
}
// Kinda cheap, but lets use the missile hits table for Battle armor
// weapons too
if (attacker instanceof BattleArmor) {
if ((wt.getInternalName() != Infantry.SWARM_MEK)
& (wt.getInternalName() != Infantry.LEG_ATTACK)
& !(wt.hasFlag(WeaponType.F_INFANTRY))) {
use_table = true;
}
}
if (use_table == true) {
double fHits = 0.0;
if (!(attacker instanceof BattleArmor)) {
if (weapon.getLinked() == null) {
return 0.0;
}
}
AmmoType at = null;
if (weapon.getLinked() != null) {
at = (AmmoType) weapon.getLinked().getType();
// Override damage by ammo type for some items
// Set LRM and MRM damage at 1.0, SRM types at 2.0,
// and ATMs at 2.4 (2.0 nominal x 1.2 for built-in
// Artemis)
fDamage = at.getDamagePerShot();
if ((wt.getAmmoType() == AmmoType.T_SRM_STREAK)
|| (wt.getAmmoType() == AmmoType.T_SRM)) {
fDamage = 2.0;
}
if (wt.getAmmoType() == AmmoType.T_ATM) {
fDamage = 2.4;
}
if ((wt.getAmmoType() == AmmoType.T_LRM_STREAK)
|| (wt.getAmmoType() == AmmoType.T_LRM)
|| (wt.getAmmoType() == AmmoType.T_MRM)) {
fDamage = 1.0;
}
}
if ((wt.getRackSize() != 40) && (wt.getRackSize() != 30)) {
fHits = expectedHitsByRackSize[wt.getRackSize()];
} else {
fHits = 2.0f * expectedHitsByRackSize[wt.getRackSize() / 2];
}
if ((wt.getAmmoType() == AmmoType.T_SRM_STREAK)
|| (wt.getAmmoType() == AmmoType.T_LRM_STREAK)) {
fHits = wt.getRackSize();
}
if ((wt.getAmmoType() == AmmoType.T_AC_ULTRA)
|| (wt.getAmmoType() == AmmoType.T_AC_ULTRA_THB)) {
fHits = expectedHitsByRackSize[2];
}
if (wt.getAmmoType() == AmmoType.T_AC_ROTARY) {
fHits = expectedHitsByRackSize[4];
}
if ((wt.getAmmoType() == AmmoType.T_AC_LBX)
|| (wt.getAmmoType() == AmmoType.T_AC_LBX_THB)) {
fHits = expectedHitsByRackSize[wt.getDamage()];
}
if ((wt.getAmmoType() == AmmoType.T_LRM)
|| (wt.getAmmoType() == AmmoType.T_SRM)) {
lnk_guide = weapon.getLinkedBy();
if ((lnk_guide != null)
&& (lnk_guide.getType() instanceof MiscType)
&& !lnk_guide.isDestroyed() && !lnk_guide.isMissing()
&& !lnk_guide.isBreached()
&& lnk_guide.getType().hasFlag(MiscType.F_ARTEMIS)) {
fHits *= 1.2f;
}
}
if (wt.getAmmoType() == AmmoType.T_MRM) {
lnk_guide = weapon.getLinkedBy();
if ((lnk_guide != null)
&& (lnk_guide.getType() instanceof MiscType)
&& !lnk_guide.isDestroyed() && !lnk_guide.isMissing()
&& !lnk_guide.isBreached()
&& lnk_guide.getType().hasFlag(MiscType.F_APOLLO)) {
fHits *= .9f;
}
}
// Most Battle Armor units have a weapon per trooper, plus their
// weapons do odd things when mounting multiples
if (attacker instanceof BattleArmor) {
// The number of troopers hitting
fHits = expectedHitsByRackSize[ba_attacker
.getShootingStrength()];
if (wt.getDamage() == WeaponType.DAMAGE_MISSILE) {
fHits *= expectedHitsByRackSize[wt.getRackSize()];
}
if (wt.getDamage() != WeaponType.DAMAGE_MISSILE) {
if (wt.getDamage() != WeaponType.DAMAGE_VARIABLE) {
fDamage = wt.getDamage();
} else {
fDamage = wt.getRackSize();
}
}
if (wt.hasFlag(WeaponType.F_MISSILE_HITS)) {
fHits *= expectedHitsByRackSize[wt.getRackSize()];
}
}
fDamage *= fHits;
if ((wt.getAmmoType() == AmmoType.T_AC_ULTRA)
|| (wt.getAmmoType() == AmmoType.T_AC_ULTRA_THB)
|| (wt.getAmmoType() == AmmoType.T_AC_ROTARY)) {
fDamage = fHits * wt.getDamage();
}
} else {
// Direct fire weapons just do a single shot
// so they don't use the missile hits table
fDamage = wt.getDamage();
// Heavy gauss and Thunderbolt LRMs do odd things with range
if (wt.getAmmoType() == AmmoType.T_GAUSS_HEAVY) {
fDamage = 25.0;
if (range > 6) {
fDamage = 20.0;
}
if (range > 13) {
fDamage = 10.0;
}
}
if ((wt.getAmmoType() == AmmoType.T_TBOLT_5) ||
(wt.getAmmoType() == AmmoType.T_TBOLT_10) ||
(wt.getAmmoType() == AmmoType.T_TBOLT_15) ||
(wt.getAmmoType() == AmmoType.T_TBOLT_20)) {
if (range <= wt.getMinimumRange()) {
fDamage *= 0.5;
}
}
// Infantry follow some special rules, but do fixed amounts of
// damage
if (attacker instanceof Infantry) {
if (wt.hasFlag(WeaponType.F_INFANTRY)) {
// Weapons fielded by conventional infantry and light BA
// Field guns should be handled under the normal weapons
// section
/*
* fDamage = 0.6f * inf_attacker.getDamage(inf_attacker.
* getShootingStrength());
*/
// TODO: fix me
fDamage = 1;
if (attacker instanceof BattleArmor) {
/*
* fDamage = inf_attacker.getDamage(ba_attacker.
* getShootingStrength());
*/
// TODO: fix me
fDamage = 1;
}
}
if (wt.getInternalName() == Infantry.LEG_ATTACK) {
// Odds change based on number of troopers. Make an
// estimate.
if (!(attacker instanceof BattleArmor)) {
total_mod = 4 + 2 * (inf_attacker.getOInternal(0) - inf_attacker
.getShootingStrength()) / 5;
} else {
total_mod = 8 - ba_attacker.getShootingStrength();
}
fDamage = 10.0; // Damage is actually 5 plus chance at crits
}
if (wt.getInternalName() == Infantry.SWARM_MEK) {
// Odds change based on number of troopers. Make an
// estimate.
// Damage is same as conventional weapons, but with chance
// for crits
if (!(attacker instanceof BattleArmor)) {
total_mod = 7 + 2 * (inf_attacker.getOInternal(0) - inf_attacker
.getShootingStrength()) / 5;
/*
* fDamage = 1.5 * inf_attacker.getDamage(inf_attacker
* .getShootingStrength());
*/