/**
* MegaMek - Copyright (C) 2005 Ben Mazur (bmazur@sev.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
package megamek.common.weapons;
import megamek.common.AmmoType;
import megamek.common.IGame;
import megamek.common.MiscType;
import megamek.common.Mounted;
import megamek.common.RangeType;
import megamek.common.ToHitData;
import megamek.common.WeaponType;
import megamek.common.actions.WeaponAttackAction;
import megamek.server.Server;
/**
* @author Jay Lawson
*/
public class AmmoBayWeaponHandler extends BayWeaponHandler {
private static final long serialVersionUID = -1618484541772117621L;
/**
* @param t
* @param w
* @param g
* @param s
*/
public AmmoBayWeaponHandler(ToHitData t, WeaponAttackAction w, IGame g, Server s) {
super(t, w, g, s);
}
/**
* Calculate the attack value based on range
* This needs to do additional work for Weapon Bays with ammo.
* I need to use the ammo within this function because I may run out of ammo
* while going through the loop
* Sine this function is called in the WeaponHandler constructor it should
* be ok to use the ammo here
* @return an <code>int</code> representing the attack value at that range.
*/
protected int calcAttackValue() {
int distance = ae.getPosition().distance(target.getPosition());
double av = 0;
int range = RangeType.rangeBracket(distance, wtype.getATRanges(), true);
for(int wId: weapon.getBayWeapons()) {
Mounted bayW = ae.getEquipment(wId);
//check the currently loaded ammo
Mounted bayWAmmo = bayW.getLinked();
if(null == bayWAmmo || bayWAmmo.getShotsLeft() < 1) {
//try loadinsg something else
ae.loadWeaponWithSameAmmo(bayW);
bayWAmmo = bayW.getLinked();
}
if(!bayW.isBreached() && !bayW.isDestroyed() && !bayW.isJammed()
&& bayWAmmo != null
&& ae.getTotalAmmoOfType(bayWAmmo.getType()) >= bayW.getCurrentShots()) {
WeaponType bayWType = ((WeaponType)bayW.getType());
//need to cycle through weapons and add av
double current_av = 0;
AmmoType atype = (AmmoType)bayWAmmo.getType();
if(range == WeaponType.RANGE_SHORT) {
current_av = bayWType.getShortAV();
} else if(range == WeaponType.RANGE_MED) {
current_av = bayWType.getMedAV();
} else if (range == WeaponType.RANGE_LONG) {
current_av = bayWType.getLongAV();
} else if (range == WeaponType.RANGE_EXT) {
current_av = bayWType.getExtAV();
}
current_av = updateAVforAmmo(current_av, atype,
bayWType, range, wId);
av = av + current_av;
//now use the ammo that we had loaded
if(current_av > 0) {
int shots = bayW.getCurrentShots();
for(int i = 0; i < shots; i++) {
if(null == bayWAmmo || bayWAmmo.getShotsLeft() < 1) {
//try loadinsg something else
ae.loadWeaponWithSameAmmo(bayW);
bayWAmmo = bayW.getLinked();
}
if(null != bayWAmmo) {
bayWAmmo.setShotsLeft(bayWAmmo.getShotsLeft() - 1);
}
}
}
//check for nukes and tele-missiles and if they are there then I will need to
//add them to an inserted attack list and reset the av
if(atype.hasFlag(AmmoType.F_NUCLEAR) || atype.hasFlag(AmmoType.F_TELE_MISSILE)) {
insertedAttacks.addElement(wId);
av = av - current_av;
}
}
}
return (int)Math.ceil(av);
}
/*
* check for special munitions and their effect on av
* TODO: it might be better to have unique weapon handlers
* for these by bay, but I am lazy
*/
protected double updateAVforAmmo(double current_av, AmmoType atype, WeaponType wtype, int range, int wId) {
//check for artemisIV
Mounted mLinker = weapon.getLinkedBy();
int bonus = 0;
if ((mLinker != null && mLinker.getType() instanceof MiscType
&& !mLinker.isDestroyed() && !mLinker.isMissing()
&& !mLinker.isBreached() && mLinker.getType().hasFlag(
MiscType.F_ARTEMIS))
&& atype.getMunitionType() == AmmoType.M_ARTEMIS_CAPABLE) {
bonus = (int)Math.ceil(atype.getRackSize() / 5.0);
if(atype.getAmmoType() == AmmoType.T_SRM) {
bonus = 2;
}
current_av = current_av + bonus;
}
if(atype.getMunitionType() == AmmoType.M_CLUSTER) {
current_av = Math.floor(0.6*current_av);
}
else if (AmmoType.T_ATM == atype.getAmmoType()) {
if (atype.getMunitionType() == AmmoType.M_EXTENDED_RANGE) {
current_av = wtype.getExtAV()/2;
} else if (atype.getMunitionType() == AmmoType.M_HIGH_EXPLOSIVE) {
current_av = 1.5 * current_av;
if(range > WeaponType.RANGE_SHORT) {
current_av = 0.0;
}
}
}
else if (atype.getAmmoType() == AmmoType.T_MML && !atype.hasFlag(AmmoType.F_MML_LRM)) {
current_av = 2 * current_av;
if(range > WeaponType.RANGE_SHORT) {
current_av = 0;
}
}
else if (atype.getAmmoType() == AmmoType.T_AR10) {
if (atype.hasFlag(AmmoType.F_AR10_KILLER_WHALE)) {
current_av = 4;
} else if (atype.hasFlag(AmmoType.F_AR10_WHITE_SHARK)) {
current_av = 3;
} else {
current_av = 2;
}
}
return current_av;
}
}