Class DamageProfile
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 ClassesModifier and TypeClassDescriptionstatic final recordPer-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
FieldsModifier and TypeFieldDescriptionstatic final intThe number of hex-side directions a unit can be attacked from or fire toward. -
Method Summary
Modifier and TypeMethodDescriptionarcSummary(int direction) doubleexpectedDamage(int range) intgunnery()booleanbooleandoublemaxDamage(int range) intmaxRange()static DamageProfileBuilds 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).static DamageProfileBuilds the damage profile for a unit at an explicit gunnery skill instead of the crew's, for what-if displays (e.g.static DamageProfileBuilds the damage profile at an explicit heat capacity instead of the unit's current one, for what-if questions about heat dissipation - e.g.doubleintThe range where the expected-damage curve peaks: the unit's optimal engagement range.doublesustainedDamage(int range)
-
Field Details
-
DIRECTIONS
public static final int DIRECTIONSThe number of hex-side directions a unit can be attacked from or fire toward.- See Also:
-
-
Method Details
-
of
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 profileuseExtremeRange- whether the TacOps extreme-range rules are in effect- Returns:
- the unit's damage profile; never
null, possibly empty (seehasWeapons())
-
of
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 profileuseExtremeRange- whether the TacOps extreme-range rules are in effectgunnery- the gunnery skill for the expected and sustained curves- Returns:
- the unit's damage profile; never
null, possibly empty (seehasWeapons())
-
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 profileuseExtremeRange- whether the TacOps extreme-range rules are in effectgunnery- the gunnery skill for the expected and sustained curvesheatCapacity- the heat dissipation budget for the sustained curve- Returns:
- the unit's damage profile; never
null, possibly empty (seehasWeapons())
-
hasCapitalScaleWeapons
public boolean hasCapitalScaleWeapons()- Returns:
trueif 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
- 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:
trueif 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
-