Classic bug: Wormhole projectile cleanup
| Bug ID | GE-BUG-010 |
|---|---|
| Affected versions | Classic 3.2d/3.2e lineage and published source |
| Status | Verified in source and release history |
| Fixed in | ge-next 0.2.4 |
| Primary source | GEFUNCS.C proximity(), cleartm(), clearitm(), and checktm(); classic 3.2d release notes |
Summary
Galactic Empire 3.2d explicitly announced that torpedoes and missiles would no longer follow a player through a wormhole. The wormhole movement code was changed to call cleartm(), but that function clears the traveler's ownership of projectiles fired at other ships. It does not clear torpedoes and missiles incoming to the traveler.
The intended 3.2d correction therefore did not work. The same mistake remains in the published classic 3.2e source.
Symptoms
Torpedoes and missiles already fired at a player continue counting down after that player enters a wormhole. They can produce tracking messages and eventually strike the ship even though it was instantaneously transported to a distant sector.
At the same time, projectiles previously fired by the wormhole traveler at other ships remain active but lose their owner. If one later hits, it is treated as having come from no user rather than from the player who fired it.
This is the opposite of the announced behavior: incoming attacks follow the traveler, while the traveler's unrelated outgoing attacks lose attribution.
Projectile representation
Classic does not keep a global projectile object containing both a source and a target. Incoming projectiles are stored directly in arrays belonging to the target ship:
target->ltorps[i].distancerecords an incoming torpedo's remaining distance.target->ltorps[i].channelrecords the firing ship's channel.target->lmissl[i]stores the equivalent missile state, including missile energy.
The periodic checktm() routine operates on the target ship and reduces these stored distances until the projectile hits or is otherwise removed. Relocating the target does not recalculate the distance from the attacker. Unless the target's array entries are cleared, their countdown simply continues in the new sector.
Cause
When a ship is pulled through a wormhole, classic changes its coordinates and then executes:
cleartm(usrn);
Despite the nearby comment saying that this clears the torpedoes and missiles, cleartm() takes an attacker channel. It walks the incoming arrays of every active ship and changes any projectile whose channel matches that attacker to 255. It does not set the projectile's distance to zero, so the projectile remains active but becomes ownerless.
For example, suppose player A has fired a torpedo at player B and player C has fired a missile at player A. The records are arranged as follows:
- B's incoming torpedo array contains an active entry whose owner is A.
- A's incoming missile array contains an active entry whose owner is C.
If A enters a wormhole, cleartm(A) finds the torpedo stored on B and changes its owner to 255. It never selects the missile stored on A because that missile's owner is C. The missile therefore continues toward A after the relocation.
The function is useful for a different event: when an attacker leaves the game or its ship is destroyed, active projectiles attributed to that channel must not later be credited to a different user who inherits the same channel. It was simply the wrong operation for moving a target through a wormhole.
Correction
ge-next 0.2.4 added the complementary clearitm() routine. Given a target ship slot, it examines that ship's own incoming torpedo and missile arrays and sets every active projectile's distance to zero. The wormhole path calls clearitm(usrn) instead of cleartm(usrn), so incoming weapons are removed while the traveler's outbound weapons retain their ownership and continue toward their existing targets.
ge-next also notifies each applicable attacker that its torpedoes or missiles have been lost. Later refinements group those notices so an attacker does not receive one duplicate message for every projectile.
The same release separately clears the traveler's jamming effect during a wormhole transition and destroys incoming ordnance when a player reaches the protected neutral sector. Those are related transition rules, but they are not the correction to the 3.2d cleartm() mistake itself.
Porting guidance
Name source-oriented and target-oriented cleanup operations distinctly. In classic's data model, clearing an attacker means scanning every target and removing or anonymizing entries by channel; clearing a target means zeroing active entries in that target's own arrays. These operations are not interchangeable.
Every instantaneous relocation should also define what happens to incoming ordnance, locks, jamming, area effects, and NPC pursuit state rather than changing coordinates independently of those decisions.
Home · Play · Reference · Versions & history · Sysop · Development · Classic bugs