Specifications for all the different types of ship in the universe
Every ship in Elite has a blueprint that defines that ship's characteristics (note that in this context, "ship" refers not only to ships, but also cargo canisters, space stations, escape pods, missiles and asteroids). These blueprints are the in-game equivalent of the last section of the Space Traders Flight Training Manual - a real life version of "Jane's Galactic Ships and Remote Colonial Construction, 5th Edition, 3205" (pub. Trantor House).
There is a lookup table at XX21 that contains the addresses of all the ship blueprints used in the game. Ship type 1 (the Sidewinder at SHIP_SIDEWINDER) is first in the table, then ship type 2 (the Viper at SHIP_VIPER) is next, and so on up to ship type 13 (the escape pod at SHIP_ESCAPE_POD). For all ships except the Python, the blueprints themselves are stored in sequence just after the table; the Python is stored at SHIP_PYTHON, just above screen memory at &7F00.
The 13 ship types are as follows, along with the configuration variables where they exist:
1. Sidewinder 2. Viper (COPS) 3. Mamba 4. Python 5. Cobra Mk III bounty hunter 6. Thargoid (THG) 7. Cobra Mk III trader (CYL) 9. Missile (MSL) 10. Asteroid (AST) 11. Cargo (OIL) 12. Thargon (TGL) 13. Escape pod (ESC)
Each ship blueprint defines a whole range of attributes, such as the ship's maximum speed, the number of missiles it can carry, and the size of the target area we need to hit with our laser. It also contains data that's used when managing the ship once it's spawned inside our local bubble of universe, like the maximum size of the ship line heap.
The blueprint also contains all the data we need to draw the ship on-screen. This includes the ship's vertices, edges and faces, the visibility distances, and the face normal scale factor, all of which are used in the ship drawing routine at LL9. See the deep dive on drawing ships for more details.
For each ship blueprint, the first 20 bytes define the main characteristics of this ship type. They are as follows:
* Byte #0 Maximum number of cargo canisters released when destroyed * Byte #1-2 The ship's targetable area, which represents how far the ship can be from the centre of our crosshairs and still be locked onto by our missiles or hit by our lasers, as described in the HITCH routine (16-bit value, 1 = low byte, 2 = high byte) * Byte #3 Edges data offset low byte (offset is from byte #0) * Byte #4 Faces data offset low byte (offset is from byte #0) * Byte #5 Maximum heap size for plotting ship = 1 + 4 * max. no of visible edges * Byte #6 Number * 4 of the vertex used for the ship's laser position, for when the ship fires its lasers * Byte #7 Explosion count = 4 * n + 6, where n = number of vertices used as origins for explosion clouds * Byte #8 Number of vertices * 6 * Byte #9 Number of edges * Byte #10-11 The bounty awarded for the destruction of this ship in Cr * 10 (16-bit little-endian value, 10 = low byte, 11 = high byte) * Byte #12 Number of faces * 4 * Byte #13 Visibility distance, beyond which we show the ship as a dot * Byte #14 Maximum energy/shields * Byte #15 Maximum speed * Byte #16 Edges data offset high byte (can be negative and point to another ship's edge net) * Byte #17 Faces data offset high byte * Byte #18 Face normals are scaled down by 2 ^ this value to enable us to store more accurate fractional data in the table * Byte #19 %00 lll mmm, where: * Bits 0-2 = number of missiles * Bits 3-5 = laser power If we are hit by this ship's lasers, the damage taken is half the valuie of this whole byte, i.e. %000lllmm
Next come the vertex definitions. Each vertex is made up of eight values stored in six bytes, as follows:
* Byte #0 Magnitude of the vertex's x-coordinate, with the origin in the middle of the ship * Byte #1 Magnitude of the vertex's y-coordinate * Byte #2 Magnitude of the vertex's z-coordinate * Byte #3 %xyz vvvvv, where: * Bits 0-4 = visibility distance, beyond which the vertex is not shown * Bits 7-5 = the sign bits of x, y and z * Byte #4 %ffff ffff, where: * Bits 0-3 = the number of face 1 * Bits 4-7 = the number of face 2 * Byte #5 %ffff ffff, where: * Bits 0-3 = the number of face 3 * Bits 4-7 = the number of face 4
Then we have the edge definitions. Each edge is made up of five values stored in four bytes, as follows:
* Byte #0 Visibility distance, beyond which the edge is not shown * Byte #1 %ffff ffff, where: * Bits 0-3 = the number of face 1 * Bits 4-7 = the number of face 2 * Byte #2 The number of the vertex at the start of the edge * Byte #3 The number of the vertex at the end of the edge
Finally we have the face definitions. Each face is made up of four values stored in four bytes, as follows. Note that the visibility distance works in the opposite way for faces than for the ship, vertices and edges, in that the face is always shown when it's further away than the visibility distance.
* Byte #0 %xyz vvvvv, where: * Bits 0-4 = visibility distance, beyond which the face is always shown * Bits 7-5 = the sign bits of normal_x, normal_y and normal_z * Byte #1 Magnitude of the face normal's x-coordinate, normal_x * Byte #2 Magnitude of the face normal's y-coordinate, normal_y * Byte #3 Magnitude of the face normal's z-coordinate, normal_z
To make the source code easier to follow, we use three macros (called VERTEX, EDGE and FACE) that let us separate out the different values, and which squash the data into the above bytes at compile time.