Skip to content

Commit

Permalink
Fix for #4801: NPE while Princess moves BAs
Browse files Browse the repository at this point in the history
This fixes an issue introduced by my attempt to add Field Gun / Field
Artillery expected damage calculations for infantry units under
Princess.

Unfortunately, I didn't realize that the same code path was used by all
non-infantry units when Princess projects how much damage _any_ unit
will take; in this case, BA attackers trying to compute expected damage
against non-enemy targets.

The root of the issue is trying to dereference linked ammo for BA
weapons, which don't have that concept in some cases.  This throws
an NPE, which gets caught, causing a null 'mp' object to be returned,
which creates a _new_ NPE.

Fix is to clean up that area of code and restrict the special weapon
handling to infantry only.  All others, including BAs, will go back
to the previous method of projecting expected damage.

Testing:

- Re-ran reporter's attached saved game.
- Confirmed the update for field guns / field artillery still works
  correctly.
- Ran all unit tests.
  • Loading branch information
Sleet01 committed Sep 24, 2023
1 parent 8c988c6 commit 683fc91
Showing 1 changed file with 15 additions and 14 deletions.
29 changes: 15 additions & 14 deletions megamek/src/megamek/client/bot/princess/InfantryFireControl.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ public double getMaxDamageAtRange(final MovePath shooterPath, final MovePath tar
boolean shooterIsActualInfantry = shooter.hasETypeFlag(Entity.ETYPE_INFANTRY)
&& !shooter.hasETypeFlag(Entity.ETYPE_BATTLEARMOR);
// field guns can't fire if the unit in question moved
boolean fieldGunsDoDamage = (shooterIsActualInfantry && shooterPath.getMpUsed() == 0)
|| !shooterIsActualInfantry;
boolean otherWeaponsMayShoot = !shooterIsActualInfantry || shooterPath.getMpUsed() == 0;
boolean inBuilding = Compute.isInBuilding(target.getGame(), targetPath.getFinalElevation(),
targetPath.getFinalCoords());
boolean inOpen = ServerHelper.infantryInOpen(target, targetHex, target.getGame(), targetIsPlatoon, false,
Expand Down Expand Up @@ -96,8 +95,8 @@ public double getMaxDamageAtRange(final MovePath shooterPath, final MovePath tar
// weapon damage, multiply by building dmg reduction.
// 4. Shooter is non-infantry, target is infantry in "cover". Use
// "directBlowInfantryDamage".
// 5. Shooter is non-infantry, target is non-infantry. Use base
// class.
// 5. Shooter is infantry with field gun / field artillery and needs special damage calc.
// 6. Shooter is non-infantry, target is non-infantry. Use base class.

// case 1
if (weaponType.hasFlag(WeaponType.F_INFANTRY)) {
Expand All @@ -113,7 +112,7 @@ public double getMaxDamageAtRange(final MovePath shooterPath, final MovePath tar
* infantryCount;
// field guns can't fire if the infantry unit has done anything
// other than turning
} else if (targetIsActualInfantry && fieldGunsDoDamage) {
} else if (targetIsActualInfantry && otherWeaponsMayShoot) {
double damage = 0;

// if we're outside, use the direct blow infantry damage
Expand All @@ -134,15 +133,17 @@ public double getMaxDamageAtRange(final MovePath shooterPath, final MovePath tar
}

maxFGDamage += damage;
// field guns can't fire if the infantry unit has done anything
// other than turning
// case 5
} else if (fieldGunsDoDamage) {
// Some FGs are artillery, so check both damage/shot * shot num _and_ rack size.
AmmoType ammoType = (AmmoType) weapon.getLinked().getType();
int wDamage = (weaponType.hasFlag(F_ARTILLERY) ? weaponType.rackSize : weaponType.getDamage());
int ammoDamage = ammoType.getDamagePerShot()*ammoType.getShots();
maxFGDamage += Math.max(wDamage, ammoDamage);
} else if (otherWeaponsMayShoot) {
// case 5
if (shooter.isInfantry()) {
// field guns can't fire if the infantry unit has done anything
// other than turning, so we only get here if infantry has not used MP.
// All valid Infantry Field Weapons can consider rackSize as their damage.
maxFGDamage += weaponType.rackSize;
// Case 6: all other unit types / weapons
} else {
maxFGDamage += weaponType.getDamage();
}
}
}

Expand Down

0 comments on commit 683fc91

Please sign in to comment.