Class DamageProfile

java.lang.Object
megamek.common.analysis.DamageProfile

public final class DamageProfile extends Object
An immutable per-unit damage-versus-range curve, computed from the unit's actual weapons and loaded ammunition.

Three curves are exposed, indexed by range in hexes:

  • maxDamage(int) - every functioning weapon that reaches the range, no to-hit weighting. Cluster weapons count their full rack.
  • expectedDamage(int) - each weapon's damage weighted by its 2d6 hit probability at that range (gunnery + range bracket modifier + minimum range penalty). Cluster weapons use the expected value of the cluster hits table instead of the full rack.
  • sustainedDamage(int) - the best heat-sustainable subset of weapons by expected damage: weapons are added in expected-damage-per-heat order until the unit's heat dissipation is spent. Equal to the expected curve for units that do not track heat.

The curves are unit properties, not situation properties: no terrain, movement, or target modifiers are included - those belong to fire control at attack time. The gunnery skill baked into the expected and sustained curves is the crew's actual gunnery (4 if the unit has no crew). Ammunition is chosen per range by best expected damage, mirroring how a player would load for the engagement. Weapon facing is ignored; the curve is the unit's best case in any direction.

Infantry and battle armor follow their TW attack mechanics: a conventional platoon's small arms deal ceil(per-trooper damage x shooting troopers) as one attack over the R/2R/3R infantry brackets; a battle armor squad's direct-fire weapons roll the cluster table on the number of firing suits, and its missile racks pool across suits into one larger cluster roll. Crew-served field guns and squad support weapons fire once. ProtoMeks and all other unit types resolve as individually mounted weapons.

Known approximations: artillery is treated as a direct-fire weapon dealing its rack size; cluster-roll bonuses from fire-control equipment (Artemis, Apollo) are not applied; infantry use the standard bracket to-hit modifiers rather than the point-blank special cases.

Build cost is O(weapons x maxRange) with small constants; instances are cheap enough to rebuild once per game phase. Consumers that query per candidate path should cache the instance per entity (see the CASPAR bot's phase-start caches for the intended lifecycle).

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final record 
    Per-direction firepower summary for one of the six hex-side directions relative to the unit's facing (0 = front, counting clockwise: 1 = front-right, 2 = rear-right, 3 = rear, 4 = rear-left, 5 = front-left).
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    The number of hex-side directions a unit can be attacked from or fire toward.
  • Method Summary

    Modifier and Type
    Method
    Description
    arcSummary(int direction)
     
    double
    expectedDamage(int range)
     
    int
     
    boolean
     
    boolean
     
    double
    maxDamage(int range)
     
    int
     
    of(Entity entity, boolean useExtremeRange)
    Builds the damage profile for a unit from its current weapon and ammunition state, using the crew's gunnery skill (4 if the unit has no crew).
    of(Entity entity, boolean useExtremeRange, int gunnery)
    Builds the damage profile for a unit at an explicit gunnery skill instead of the crew's, for what-if displays (e.g.
    of(Entity entity, boolean useExtremeRange, int gunnery, int heatCapacity)
    Builds the damage profile at an explicit heat capacity instead of the unit's current one, for what-if questions about heat dissipation - e.g.
    double
     
    int
    The range where the expected-damage curve peaks: the unit's optimal engagement range.
    double
    sustainedDamage(int range)
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • DIRECTIONS

      public static final int DIRECTIONS
      The number of hex-side directions a unit can be attacked from or fire toward.
      See Also:
  • Method Details

    • of

      public static DamageProfile of(Entity entity, boolean useExtremeRange)
      Builds the damage profile for a unit from its current weapon and ammunition state, using the crew's gunnery skill (4 if the unit has no crew). Destroyed and out-of-ammo weapons contribute nothing, so a profile built mid-game reflects battle damage as of when it was built.
      Parameters:
      entity - the unit to profile
      useExtremeRange - whether the TacOps extreme-range rules are in effect
      Returns:
      the unit's damage profile; never null, possibly empty (see hasWeapons())
    • of

      public static DamageProfile of(Entity entity, boolean useExtremeRange, int gunnery)
      Builds the damage profile for a unit at an explicit gunnery skill instead of the crew's, for what-if displays (e.g. the unit viewer's BV gunnery field).
      Parameters:
      entity - the unit to profile
      useExtremeRange - whether the TacOps extreme-range rules are in effect
      gunnery - the gunnery skill for the expected and sustained curves
      Returns:
      the unit's damage profile; never null, possibly empty (see hasWeapons())
    • of

      public static DamageProfile of(Entity entity, boolean useExtremeRange, int gunnery, int heatCapacity)
      Builds the damage profile at an explicit heat capacity instead of the unit's current one, for what-if questions about heat dissipation - e.g. the sustained curve a Mek would have standing in water (Entity.getHeatCapacityWithWater()). Only the sustained curve depends on it.
      Parameters:
      entity - the unit to profile
      useExtremeRange - whether the TacOps extreme-range rules are in effect
      gunnery - the gunnery skill for the expected and sustained curves
      heatCapacity - the heat dissipation budget for the sustained curve
      Returns:
      the unit's damage profile; never null, possibly empty (see hasWeapons())
    • hasCapitalScaleWeapons

      public boolean hasCapitalScaleWeapons()
      Returns:
      true if any contributing weapon is capital or sub-capital scale. The curves are always in standard damage points (capital converts at x10); displays may use this to relabel their axes in capital scale for naval reading.
    • arcSummary

      public DamageProfile.ArcSummary arcSummary(int direction)
      Parameters:
      direction - the hex-side direction relative to the unit's facing: 0 = front, clockwise (1 = front-right, 2 = rear-right, 3 = rear, 4 = rear-left, 5 = front-left)
      Returns:
      the firepower summary for that direction; an all-zero summary if no weapon bears
    • maxDamage

      public double maxDamage(int range)
      Parameters:
      range - the range in hexes (0 is treated as point-blank, i.e. range 1)
      Returns:
      the total damage of every functioning weapon that reaches this range, unweighted
    • expectedDamage

      public double expectedDamage(int range)
      Parameters:
      range - the range in hexes (0 is treated as point-blank, i.e. range 1)
      Returns:
      the to-hit-weighted damage at this range, using the crew's gunnery
    • sustainedDamage

      public double sustainedDamage(int range)
      Parameters:
      range - the range in hexes (0 is treated as point-blank, i.e. range 1)
      Returns:
      the to-hit-weighted damage of the best heat-sustainable weapon subset at this range
    • maxRange

      public int maxRange()
      Returns:
      the longest range at which any functioning weapon can deal damage, under the range rules the profile was built with; 0 if the unit has no usable weapons
    • hasWeapons

      public boolean hasWeapons()
      Returns:
      true if the unit had at least one functioning weapon with a nonzero damage curve when the profile was built. Replaces sentinel values - consumers decide what "no weapons" means for them.
    • peakExpectedRange

      public int peakExpectedRange()
      The range where the expected-damage curve peaks: the unit's optimal engagement range. Ties go to the longer range, since equal damage from farther away is strictly safer.
      Returns:
      the optimal range in hexes, or 0 if the unit has no usable weapons
    • peakExpectedDamage

      public double peakExpectedDamage()
      Returns:
      the peak of the expected-damage curve; the unit's threat at its best range. 0 if the unit has no usable weapons.
    • gunnery

      public int gunnery()
      Returns:
      the gunnery skill baked into the expected and sustained curves