# Weapons, collisions and enemy behaviour

[Gameplay overview](gameplay.md) · [All tuning tables and handler addresses](gameplay/tables.json).
Numbers and addresses below refer to the normal 3.42 flight engine. Quality means
**1–8**, although its stored index is 0–7.

## Damage and collision rules

Common scenery/enemy damage is handled at `b6c8`; similar inline helpers serve
orbs, radar and fuel. An attacking object's live flags select damage:

| Attacker flags | Damage to common hit points |
| --- | ---: |
| Neither `40h` nor `80h` | 1 |
| `40h` | 6 |
| `80h`, including both bits | 25 |

A player-aircraft collision sentinel (`DI=ffff`) destroys a common target outright.
Individual types can reject an attack before reaching this helper. Player aircraft
use the separate randomized damage channels described in [flight dynamics](flight-dynamics.md).
For player contact, `7b8c` selects 1, 6 or **75** damage events according to the
contacting object's flags. Forcefields rate-limit their repeated damage using the
fast clock, then double the selected count. Consequently, scenery hit points and
hits accumulated by the player are not interchangeable units.

Stored template health includes:

| Object | Hit points |
| --- | ---: |
| Generator orb | 65 |
| Fuel dump / Tet | 13 |
| KLA site / vehicle site | 50 |
| AAA site | 6 |
| Ground vehicle | 5 |
| KLA | 2 |
| Saucer / objective saucer | 50 |
| Saucer site | 100 |
| Mortar | 40 |
| Alien | 3 |
| Mindbender | 1, with weapon restrictions |
| Ground crew | 1 |
| Radar / tower | 10 |

These are initial templates, not promises that a mission cannot alter state or a
handler cannot restore health. A quality-5 orb, for example, restores its health
and rejects normal weapon damage.

There are several collision paths. The **strict axis-aligned box** routine at
`7586` requires overlap on X, Y and Z; touching exactly at the sum of half-extents
is not enough. Zero X extent disables that test. Native probes cover all axes,
both signs, large signed coordinates and 16-bit carries. Some general contacts
instead use centre distance, and fast bullets/missiles have additional
velocity/dot-product checks (`7742` onwards). The subsequent
[native reconstruction](https://github.com/Lost-Engines/corncob-cpp/blob/master/docs/reconstruction.md#verification) checks 512 fast and 512 ordinary
projectile contacts against the original routines; this report retains the
higher-level description of the separate paths.

A byte at object `+13h` is also compared before object-object collision. Equal
collision-group tags are skipped in the relevant paths. Templates distinguish
player shots, friendly objects, hostile objects and installations; launch/effect
code can change the tag. This is not a modern universal allegiance system: blast
fragments, direct projectiles, the person and the aircraft take different paths.
The supplied manual's friendly-fire tactics cannot be reduced to “all projectiles
collide with all other projectiles.”

## Player weapons

| Weapon | Native launch/update | Behaviour |
| --- | --- | --- |
| Guns | `08e8`; bullets `bdef` | Separate 32-record pool; forward launch velocity and alternating muzzle offset; ordinary damage class 1 |
| Shift cannon mode | `4430–4456` | Changes projectile speed from 4400 to 700 and lifetime from 96 to 48; this is a real projectile-mode difference |
| Missile | `b0a9`; update `ae28` | Type 21, six-hit flags, 100-frame initial lifetime; accelerates along its existing velocity, not a guided enemy KLA |
| Air-dropped bomb | `afeb`; update `a92b` | Type 20, inherits scaled aircraft motion; decelerates and falls; proximity-armed after clearing the player |
| Pistol | `08e8` on-foot branch | Uses gun machinery from the person's viewpoint; finite 20-round supply |
| Assassin bomb | `4704–474c`; shared type-20 update | One carried charge; planted stationary, marked special; D arms/releases it |

The missile acceleration multiplies each velocity component by **1000/890**, while
its remaining lifetime is at least 89 and speed is not above 3000. It therefore
accelerates only during the early portion of its flight. It does not search for
a target. Native initial velocity uses the aircraft's forward airflow plus **125**;
this is why the fast black aircraft can initially overtake its own missiles.

Gun launch velocity likewise uses forward airflow plus the selected gun speed.
The cannon-mode numbers are raw launch/lifetime coefficients, not a claim that
holding Shift changes the common target-damage flag. A complete reconstruction
should retain the original separate bullet allocation and collision handling.

Guns and missiles are replenishing weapons, with firing/recovery counters rather
than a finite ammunition inventory. Continued firing increases counters; recovery
reduces them. Timing includes BIOS-rate interrupt counters and frame processing,
so a single “shots per second” number would conceal the original cadence.

Bomb supply is capped at **three** (`4658`). Each successful drop consumes one and
restarts the replacement timer. The timer is adjusted for accelerated time; its
threshold comes from DS:`0e4f`. Aircraft entry resets the available supply to three.
The source's full initial values remain available alongside the code rather than
inventing a timing constant from a rendered recording.

Bomb detonation creates **15** incendiary fragments; one alternate bomb flag cuts
that to **five**. When sufficiently near the ground (Z high word zero and low word
at most **10000 cm**), the object becomes a type-32 crater at Z=10. Ordinary craters
cool through a timer; special ones remain hot. Fragments, blast effects and the
crater can harm nearby objects after the initial impact. A bomb is not one radial
health subtraction.

The planted bomb does not explode immediately when D is pressed: the native code
arms it, clears its planted-state bit, enlarges its collision extent and resumes
motion. This confirms the manual's description of the charge dropping into a target.
It also explains its warning that a nearby forcefield can intercept the charge
before the intended victim does.

The explosion model is a white/yellow/red sequence, with diameters 2500, 4000 and
6000, selected from its five-frame lifetime. The damaging flags of a spawned
explosion depend on its cause; visually similar explosions are not necessarily
equally dangerous.

## KLA deathballs and their launchers

Handler `abd2` uses the twelve-word quality table at DS:`ec6d`.
The deathball aims directly at the current target vector, not a projected intercept.
Angular error is reduced gradually, with separate turn-rate limits. Small enough
error enables the lock colour flash and changes its target speed. A shared speed
helper relaxes current speed toward a target and adds bounded random variation.
The highest-quality rows can turn faster, accelerate to different speeds and spin
at different rates.

Selected table values, in raw engine units:

| Quality | Heading/pitch limits | Normal target speed | Locked target speed | Lock-error threshold |
| --- | --- | ---: | ---: | ---: |
| 1 | 50 / 50 | 550 | 800 | 1500 |
| 2 | 50 / 50 | 800 | 1100 | 1000 |
| 3 | 70 / 70 | 650 | 800 | 1000 |
| 4 | 90 / 90 | 650 | 800 | 500 |
| 5 | 90 / 90 | 750 | 900 | 500 |
| 6 | 100 / 100 | 800 | 1200 | 500 |
| 7 | 120 / 120 | 750 | 1000 | 200 |
| 8 | 150 / 150 | 825 | 1200 | 500 |

A new KLA has a launch delay before full steering. It can stop/expire when target
resolution fails; it also avoids continuing downward near the ground. The warning
sound uses distance and quality-dependent state, matching the manual's description
of different warning pitches.

The KLA-site handler `b6f6` checks its countdown and a local count limit before
spawning. Site quality passes through to the launched deathball. The reset value
is **400** for every quality in this table. Surviving a hit resets the launch timer,
so gunfire can suppress a launcher before destroying it. The timer is not a
wall-clock duration independent of rendering.

## AAA

Handler `a64c` uses six-word rows at DS:`ed61`. It calculates bearing/elevation,
limits tracking speed, and may add a velocity-based lead to the target vector.
A ground-mounted battery enforces a minimum upward firing angle rather than firing
freely through neighbouring installations.

| Quality | Fire threshold | Shell jitter | Turn limits | Leads target? |
| --- | ---: | ---: | --- | --- |
| 1 | 500 | 100 | 30 / 30 | No |
| 2 | 1000 | 50 | 50 / 50 | No |
| 3 | 1000 | 50 | 50 / 50 | No |
| 4 | 1500 | 30 | 50 / 50 | **Yes** |
| 5 | 1500 | 30 | 50 / 50 | Yes |
| 6 | 2000 | 30 | 70 / 70 | Yes |
| 7 | 3000 | 10 | 120 / 120 | Yes |
| 8 | 4000 | 10 | 500 / 500 | Yes |

The firing threshold is compared against a full 16-bit random result per update.
Tracking is time-scaled, but this firing draw is not simply a fixed-rate timer.
“Shell jitter” is passed into the shell's motion state; it is not necessarily
identical to a one-off launch-cone error.

The Other Worlds manual says the lower four qualities do not lead. **The supplied
normal 3.42 table enables lead at quality 4.** This is a concrete discrepancy, not
an assumption that the manual's indexing is authoritative.

Shell handler `a8a0` detonates on contact, at the end of its timer and probabilistically
near the player's altitude. It creates a blast and fragments, then clears the
shell. Its collision extent expands to 6000. This is why near misses matter and
why gunfire can protect the aircraft by triggering shells farther away.

## Ground vehicles and sites

Handler `b2cc` is shared by hostile vehicles and the rescue van, with type/tag
checks distinguishing the latter. The nine-word quality table at DS:`ee8d` sets
body/panel colours, near/far speed, pursuit probability, direction-change frequency
and weaving. Motion alternates between random headings and pursuit. It is not a
route-following road vehicle AI.

When pursuing a person, the vehicle starts pulling the viewpoint toward it at
range **256**, stops close at **100**, and uses **32** for the rescue handoff.
These distances use the native range helper's **1/64 position scale**, so they
represent approximately **163.84 m, 64 m and 20.48 m**, respectively—not centimetres.
Hostile vehicles can capture; the rescue van marks a safe rescue and ends the sortie.

Special vehicles accept player gun, missile and explosion types in the explicit
collision filter (`b306`), rejecting several other kinds of collision. Destroyed
vehicles enter a temporary wreck state rather than simply disappearing. Vehicle
sites have a local live-vehicle cap of at least four, or their local site count
if larger. Surviving a hit resets the launch timer to three times the base reset.

## Saucers and sites

Handler `c102` uses fourteen-word rows at DS:`efe7`. A saucer maintains a nominal
altitude near **196608 cm**, damps vertical velocity, and adds quality-dependent
vertical/horizontal oscillation. Its low state bits select four behaviours:

| Stored state | Handler | Horizontal change |
| --- | --- | --- |
| 0 | `c0d6` | Retreat: subtract normalized base-minus-object vector |
| 2 | `c0b8` | Move sideways using a perpendicular vector |
| 4 | `c086` | Approach using twice that vector |
| 6 | `c0f2` | Coast; no direct horizontal addition in this state routine |

The reference vector is calculated against DS:`02a9`, the current base/target
location used by this logic (`c531`), rather than assuming every saucer is a dogfighter
homing on the player's nose. A probabilistic transition advances through these
states in order and wraps. Exit probabilities differ by quality; approach also
changes when damaged or near the reference. Native probes confirm the four vector
operations and transition coefficients.

At close horizontal range the saucer can drop bombs; farther away it may launch
KLAs subject to quality/count limits. A separate high byte in the weapons word
allows onboard AAA: qualities **2, 4, 6 and 8** enable this path in the extracted
table. It reuses the AAA handler through a temporary object, limiting the selected
AAA quality to index 5 (display quality 6). The saucer is a combination of movement,
bombing, missile and gun systems, not one generic shooting timer.

A fatally hit saucer clears its live collision bit, receives random angular
increments and falls with gravity/drag; reaching low altitude produces debris.
An objective saucer also marks its objective complete. Other objective-saucer
states can repair/reset it according to its flags/timer. Saucer sites regenerate
craft when the local site/craft census permits and a random launch check succeeds.

## Passive hazards, aliens and special targets

| Type | Recovered behaviour |
| --- | --- |
| Solid forcefields | Collision wakes their visible geometry; timer hides it again; generator census can remove them (`b9bf`) |
| Wire/step fields | Remain visible and animate; generator census can remove them (`ba05`) |
| Balloons | Vertical motion, altitude-dependent reversal and quality-dependent random reversal; ignore ordinary collision destruction (`b88a`) |
| Bee swarms | Randomized orientation, then shared balloon movement (`b875`) |
| Mortar | Distance-limited periodic creation of explosive fragments (`b91c`) |
| Mindbender | Distorts nearby aircraft view; accepts bombs/craters only; special flag additionally requires planted-bomb lineage (`c5df`) |
| Tet | A separate destructible installation counted with fuel by one orb objective (`c673`) |
| Alien | Randomized hopping/motion; can capture a person; bullet-only destruction gate (`c6cc`) |
| Shell | Destruction spawns a quality-selected vehicle site, mortar, KLA site, AAA, balloon, swarm or fuel dump (`bea1`) |
| Crew/spy | Proximity gesture; black spy completes an objective on approach; ordinary crew can be shot (`8cfd`) |

Mindbender weapon filtering has been executed for every combination of ordinary /
special target, planted flag, and six attacking object types. A bomb-like visual
or large damage amount alone does not bypass the filter.

The mindbender's distortion range test is **1000 native range units**, approximately
640 m. Its distortion magnitude is quadratic in proximity. Special generator orbs
also attract the aircraft: the attraction is calculated from the relative vector
and an inverse squared-range term with a lower bound (`bbe1`). Neither is just a
palette animation.

A generator orb powers the local fields through the per-frame census. A field
notices that generators existed previously but none remain, then clears itself.
This is local active-world logic; there is no individually stored electrical wire
link from every field to one specific orb.
