Classic bug: Phaser durability uses cargo capacity

Bug ID GE-BUG-025
Affected versions Classic 3.2e and published classic source
Status Verified in source; probable incomplete conversion to DAMF
Fixed in ge-next 0.2
Primary source Standard and hyper-phaser damage scaling versus ship-class DAMF

Summary

Classic GE calculates resistance to standard and hyper-phasers from a ship class's maximum cargo capacity. Mines, torpedoes, and missiles instead use the class's configurable damage factor (DAMF). The result is two different durability systems operating at the same time: a ship can be fragile against ordnance but extraordinarily resistant to phasers merely because it has a large cargo hold.

This appears to be a remnant of GE's older, size-based damage model. GE 3.2e introduced the class DAMF setting and its release notes state that damage was "no longer a function of size". Most weapon paths were converted to DAMF, but the two phaser paths retained their inline cargo-size calculation.

The source proves the inconsistent behavior. Calling it an oversight is an inference: the release notes do not explicitly say that phasers were converted. Their broad description of DAMF, however, gives no indication that phasers were intended to remain an exception.

The two durability formulas

For mines, torpedoes, and missiles, classic calls ton_fact(). Its effective divisor is:

DAMF / 100

A DAMF of 100 is neutral. A DAMF of 200 divides incoming damage by 2, allowing the ship to withstand approximately twice as much of that damage. A DAMF below 100 increases the damage.

Standard and hyper-phasers do not call ton_fact() in classic. Their effective divisor is calculated independently:

1 + (class maximum cargo tons / 15000)

The code uses the class's configured maximum cargo capacity, not the ship's current cargo weight. Emptying a ship therefore does not remove this protection. Cargo capacity is acting as an undocumented second DAMF that applies only to phasers.

Gameplay consequences

The mismatch undermines the reason DAMF was added. The 3.2e release notes explain that the new setting permits large ships that are easy to damage and small ships that are hard to damage. That distinction works against mines, torpedoes, and missiles, but cargo capacity still decides phaser durability.

This produces several counterintuitive combinations:

  • A high-capacity freighter can absorb far more phaser damage than its DAMF permits against ordnance.
  • A compact combat ship with a high DAMF receives its intended protection from ordnance, but not from phasers.
  • Two classes with the same DAMF can have radically different phaser durability.
  • A class can be deliberately configured as large but fragile, yet remain very difficult to destroy with phasers.

The Sarten Obliterator is the most conspicuous example. The classic class table gives it a cargo capacity of 234,000 tons and a DAMF of 500:

Ordnance divisor:  500 / 100 = 5.0
Phaser divisor:    1 + 234000 / 15000 = 16.6

It therefore receives about 20% of calculated mine, torpedo, and missile damage, but only about 6% of calculated phaser damage. Its cargo-derived phaser protection is equivalent to a DAMF of 1660, over three times its configured DAMF. This is a major reason classic Sarten Obliterators are so difficult to pick apart with long-range phaser fire; it is not special Sarten combat logic.

For comparison, a classic Cyberquad has 12,500 tons of cargo capacity and a DAMF of 100:

Ordnance divisor:  100 / 100 = 1.0
Phaser divisor:    1 + 12500 / 15000 = 1.833...

The Cyberquad has no configured DAMF protection against ordnance, yet its cargo capacity alone removes about 45% of incoming phaser damage. Thus even ordinary classes do not receive consistent damage treatment.

See DAMF for more gameplay context and class comparisons.

Cause

GE 3.2e replaced a reserved ship-class field with SnnDAMF. The common ton_fact() helper applies it to several weapon types:

temp = damfact /
       ((double)(shipclass[ptr->shpclass].damfact) / 100.0);

The standard and hyper-phaser routines instead retained the earlier inline calculation based on max_tons and TONFACT:

tonfact = 1.0 +
          ((double)(shipclass[wptr->shpclass].max_tons) / TONFACT);
factor = factor / tonfact;

Because both phaser paths contain this legacy formula, both kinds of phaser fire exhibit the bug.

Correction in ge-next

ge-next 0.2 changed both standard and hyper-phaser damage to pass through ton_fact(). Maximum cargo capacity no longer grants hidden phaser protection, and the class DAMF consistently controls durability against mines, torpedoes, missiles, and phasers.

This is necessarily a balance change rather than a purely invisible repair. Ships whose large holds made them unusually phaser-resistant become easier to damage with phasers unless their configured DAMF is raised. Conversely, a compact class with a high DAMF finally receives that protection against phasers too.

Porting notes

Ports seeking exact classic combat behavior must preserve the cargo divisor in both phaser paths. Ports treating DAMF as the class-wide weapon-durability setting should route both standard and hyper-phaser damage through the same DAMF helper used by mines, torpedoes, and missiles.

Special fixed or environmental damage, such as a planetary collision, is a separate design question and should not be assumed to use DAMF merely because the ordinary weapon paths do.