diff --git a/megamek/i18n/megamek/common/report-messages.properties b/megamek/i18n/megamek/common/report-messages.properties index 1de020d1164..dba621a1c8c 100755 --- a/megamek/i18n/megamek/common/report-messages.properties +++ b/megamek/i18n/megamek/common/report-messages.properties @@ -16,6 +16,7 @@ # 0 through 999 -- System messages? (reserved at the moment) +950= # Email subject lines 990=MegaMek Deployment Report 991=MegaMek Round # Report diff --git a/megamek/src/megamek/common/Compute.java b/megamek/src/megamek/common/Compute.java index b0ae48d0fa3..e48a9404468 100644 --- a/megamek/src/megamek/common/Compute.java +++ b/megamek/src/megamek/common/Compute.java @@ -6400,10 +6400,11 @@ public static int directBlowBADamage(double damage, int damageType, * Used to get a human-readable string that represents the passed damage * type. * - * @param damageType - * @return + * @param damageType The dmaageType constant + * @param burstMultiplier The multiplier for burst damage, used by machine gun arrays against conventional infantry + * @return A string representation of the damage type */ - public static String getDamageTypeString(int damageType) { + public static String getDamageTypeString(int damageType, int burstMultiplier) { switch (damageType) { case WeaponType.WEAPON_DIRECT_FIRE: return Messages.getString("WeaponType.DirectFire"); @@ -6417,6 +6418,7 @@ public static String getDamageTypeString(int damageType) { case WeaponType.WEAPON_CLUSTER_MISSILE_3D6: return Messages.getString("WeaponType.Missile"); case WeaponType.WEAPON_BURST_HALFD6: + return Messages.getString("WeaponType.BurstHalf"); case WeaponType.WEAPON_BURST_1D6: case WeaponType.WEAPON_BURST_2D6: case WeaponType.WEAPON_BURST_3D6: @@ -6425,7 +6427,8 @@ public static String getDamageTypeString(int damageType) { case WeaponType.WEAPON_BURST_6D6: case WeaponType.WEAPON_BURST_7D6: default: - return Messages.getString("WeaponType.Burst"); + return String.format("%s (%dD6)", Messages.getString("WeaponType.Burst"), + burstMultiplier * (damageType - WeaponType.WEAPON_BURST_HALFD6)); } } @@ -6447,9 +6450,32 @@ public static int directBlowInfantryDamage(double damage, int mos, * @param damageType * @return */ + public static int directBlowInfantryDamage(double damage, int mos, + int damageType, boolean isNonInfantryAgainstMechanized, + boolean isAttackThruBuilding, int attackerId, Vector vReport) { + return directBlowInfantryDamage(damage, mos, damageType, isNonInfantryAgainstMechanized, + isAttackThruBuilding, attackerId, vReport, 1); + } + + /** + * Method replicates the Non-Conventional Damage against Infantry damage + * table as well as shifting for direct blows. also adjust for non-infantry + * damaging mechanized infantry + * + * @param damage The base amount of damage + * @param mos The margin of success + * @param damageType The damage class of the weapon, used to adjust damage against infantry + * @param isNonInfantryAgainstMechanized Whether this is a non-infantry attack against mechanized infantry + * @param isAttackThruBuilding Whether the attack is coming through a building hex + * @param attackerId The entity id of the attacking unit + * @param vReport The report messages vector + * @param mgaSize For machine gun array attacks, the number of linked weapons. For other weapons this should be 1. + * @return The adjusted damage + */ public static int directBlowInfantryDamage(double damage, int mos, int damageType, boolean isNonInfantryAgainstMechanized, - boolean isAttackThruBuilding, int attackerId, Vector vReport) { + boolean isAttackThruBuilding, int attackerId, Vector vReport, + int mgaSize) { int origDamageType = damageType; damageType += mos; @@ -6488,43 +6514,43 @@ public static int directBlowInfantryDamage(double damage, int mos, } break; case WeaponType.WEAPON_BURST_1D6: - damage = Compute.d6(); + damage = Compute.d6(mgaSize); if (isAttackThruBuilding) { damage *= 0.5; } break; case WeaponType.WEAPON_BURST_2D6: - damage = Compute.d6(2); + damage = Compute.d6(2 * mgaSize); if (isAttackThruBuilding) { damage *= 0.5; } break; case WeaponType.WEAPON_BURST_3D6: - damage = Compute.d6(3); + damage = Compute.d6(3 * mgaSize); if (isAttackThruBuilding) { damage *= 0.5; } break; case WeaponType.WEAPON_BURST_4D6: - damage = Compute.d6(4); + damage = Compute.d6(4 * mgaSize); if (isAttackThruBuilding) { damage *= 0.5; } break; case WeaponType.WEAPON_BURST_5D6: - damage = Compute.d6(5); + damage = Compute.d6(5 * mgaSize); if (isAttackThruBuilding) { damage *= 0.5; } break; case WeaponType.WEAPON_BURST_6D6: - damage = Compute.d6(6); + damage = Compute.d6(6 * mgaSize); if (isAttackThruBuilding) { damage *= 0.5; } break; case WeaponType.WEAPON_BURST_7D6: - damage = Compute.d6(7); + damage = Compute.d6(7 * mgaSize); if (isAttackThruBuilding) { damage *= 0.5; } @@ -6549,14 +6575,14 @@ public static int directBlowInfantryDamage(double damage, int mos, r.subject = attackerId; r.indent(2); - r.add(getDamageTypeString(origDamageType)); + r.add(getDamageTypeString(origDamageType, mgaSize)); if (origDamageType != damageType) { if (isAttackThruBuilding) { r.messageId = 9973; } else { r.messageId = 9972; } - r.add(getDamageTypeString(damageType)); + r.add(getDamageTypeString(damageType, mgaSize)); } else if (isAttackThruBuilding) { r.messageId = 9971; } else { diff --git a/megamek/src/megamek/common/MoveStep.java b/megamek/src/megamek/common/MoveStep.java index 22efe4bcc16..356b2b0e4e6 100644 --- a/megamek/src/megamek/common/MoveStep.java +++ b/megamek/src/megamek/common/MoveStep.java @@ -3903,7 +3903,6 @@ public boolean canAeroTurn(Game game) { return true; } - if (en instanceof ConvFighter) { // conventional fighters can only turn on free turns or maneuvers return false; @@ -4015,18 +4014,19 @@ public boolean isManeuver() { return maneuver; } + public Minefield getMinefield() { + return mf; + } + + /** * @return Whether this step is a maneuver that allows a free facing change. */ public boolean isFacingChangeManeuver() { return maneuver && ( maneuverType == ManeuverType.MAN_IMMELMAN - || maneuverType == ManeuverType.MAN_SPLIT_S - ); - } - - public Minefield getMinefield() { - return mf; + || maneuverType == ManeuverType.MAN_SPLIT_S + ); } /** diff --git a/megamek/src/megamek/common/weapons/MGAWeaponHandler.java b/megamek/src/megamek/common/weapons/MGAWeaponHandler.java index 53aae0ba393..9ab0d309f1e 100644 --- a/megamek/src/megamek/common/weapons/MGAWeaponHandler.java +++ b/megamek/src/megamek/common/weapons/MGAWeaponHandler.java @@ -15,17 +15,10 @@ import java.util.Vector; -import megamek.common.Building; -import megamek.common.Compute; -import megamek.common.Entity; -import megamek.common.HitData; -import megamek.common.Game; -import megamek.common.Hex; -import megamek.common.Report; -import megamek.common.ToHitData; +import megamek.common.*; import megamek.common.actions.WeaponAttackAction; +import megamek.common.options.OptionsConstants; import megamek.server.GameManager; -import megamek.server.Server; /** * @author Sebastian Brocks @@ -45,6 +38,29 @@ public MGAWeaponHandler(ToHitData t, WeaponAttackAction w, Game g, GameManager m super(t, w, g, m); } + @Override + protected int calcDamagePerHit() { + if (target.isConventionalInfantry()) { + calcDmgPerHitReport.add(new Report(950)); + int damage = Compute.directBlowInfantryDamage( + wtype.getDamage(), bDirect ? toHit.getMoS() / 3 : 0, + wtype.getInfantryDamageClass(), + ((Infantry) target).isMechanized(), + toHit.getThruBldg() != null, ae.getId(), calcDmgPerHitReport, howManyShots); + damage = applyGlancingBlowModifier(damage, true); + if (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_RANGE)) { + if (nRange > wtype.getRanges(weapon)[RangeType.RANGE_LONG]) { + damage *= 0.75; + } else if (nRange > wtype.getRanges(weapon)[RangeType.RANGE_EXTREME]) { + damage *= 0.5; + } + } + return damage; + } else { + return super.calcDamagePerHit(); + } + } + /* * (non-Javadoc) * @@ -86,24 +102,21 @@ protected int calcHits(Vector vPhaseReport) { int shotsHit; int nMod = getClusterModifiers(true); - switch (howManyShots) { - case 1: - shotsHit = 1; - break; - default: - shotsHit = allShotsHit() ? howManyShots : Compute.missilesHit( - howManyShots, nMod); - Report r = new Report(3325); - r.subject = subjectId; - r.add(shotsHit); - r.add(" shot(s) "); - r.add(toHit.getTableDesc()); - r.newlines = 0; - vPhaseReport.addElement(r); - r = new Report(3345); - r.subject = subjectId; - vPhaseReport.addElement(r); - break; + if ((howManyShots == 1) || target.isConventionalInfantry()) { + shotsHit = 1; + } else { + shotsHit = allShotsHit() ? howManyShots : Compute.missilesHit( + howManyShots, nMod); + Report r = new Report(3325); + r.subject = subjectId; + r.add(shotsHit); + r.add(" shot(s) "); + r.add(toHit.getTableDesc()); + r.newlines = 0; + vPhaseReport.addElement(r); + r = new Report(3345); + r.subject = subjectId; + vPhaseReport.addElement(r); } bSalvo = true; return shotsHit; @@ -151,7 +164,7 @@ protected void handleEntityDamage(Entity entityTarget, hit.setGeneralDamageType(generalDamageType); if (!bSalvo) { - // Each hit in the salvo get's its own hit location. + // Each hit in the salvo gets its own hit location. Report r = new Report(3405); r.subject = subjectId; r.add(toHit.getTableDesc()); diff --git a/megamek/src/megamek/common/weapons/mgs/CLMGA.java b/megamek/src/megamek/common/weapons/mgs/CLMGA.java index 797d1ec8f1b..c6bcc4b6754 100644 --- a/megamek/src/megamek/common/weapons/mgs/CLMGA.java +++ b/megamek/src/megamek/common/weapons/mgs/CLMGA.java @@ -13,16 +13,12 @@ */ package megamek.common.weapons.mgs; -import megamek.common.AmmoType; -import megamek.common.Game; -import megamek.common.Mounted; -import megamek.common.ToHitData; +import megamek.common.*; import megamek.common.actions.WeaponAttackAction; import megamek.common.weapons.AmmoWeapon; import megamek.common.weapons.AttackHandler; import megamek.common.weapons.MGAWeaponHandler; import megamek.server.GameManager; -import megamek.server.Server; /** * @author Sebastian Brocks @@ -38,6 +34,7 @@ public CLMGA() { sortingName = "MGA C"; heat = 0; damage = 2; + infDamageClass = WeaponType.WEAPON_BURST_2D6; rackSize = 2; ammoType = AmmoType.T_MG; minimumRange = WEAPON_NA;