This page contains information about the POF file format
used in Descent 1 to define robots. Please note that this is a draft and that you may find
incorrect as well as incomplete information. If you find any errors, please contact Mike Menefee.
If you want to experiment on your own and perhaps add to the
knowledge about the POF file format here is a list of all POFs found in Descent (1). The
files are stored in the HOG file in the older versions of Descent and the PIG file
starting with 1.4. If you extract one of them and place it your descent directory Descent
will read your file instead. This way you can modify it without damaging the original file
still found in the HOG/PIG file. When you delete your file, descent will read from HOG/PIG
as before.
You should start by making a hex-dump of the entire file and
then locate blocks. (See General POF structure)
Here you have a complete listing of all POF files in descent
1. Note that some files exist in two versions, e.g. robot01.pof and robot01s.pof. The
version that ends with a 's' is simpler and thus takes less time to draw. This is used if
you decrease "object complexity" in the menu "detail level". All
simple versions in Descent 1 have one sub-object (except robot38s.pof)
Robot01.pof, for example, contains the definition of
"Class 1 Drone". The robot body is defined using 9 points, numbered from 0 to 8.
These are defined in a DEFP_START structure. The points are then used to define 14
triangles using 14 TMAPPOLY structures.
| boss01.pof |
|
| boss02.pof |
|
| cmissile.pof |
|
| exit01.pof |
Exit seen when ship reaches surface? |
| exit01d.pof |
|
| flare.pof |
|
| fusion1.pof |
|
| fusion2.pof |
|
| laser1-1.pof |
|
| laser1-2.pof |
|
| laser11s.pof |
|
| laser12s.pof |
|
| laser2-1.pof |
|
| laser2-2.pof |
|
| laser21s.pof |
|
| laser22s.pof |
|
| laser3-1.pof |
|
| laser3-2.pof |
|
| laser31s.pof |
|
| laser32s.pof |
|
| laser4-1.pof |
|
| laser4-2.pof |
|
| laser41s.pof |
|
| laser42s.pof |
|
| mmissile.pof |
|
| pship1.pof |
Your ship? |
| pship1b.pof |
Your ship? |
| pship1s.pof |
Your ship? |
| reactor.pof |
|
| reactor2.pof |
|
| robot01.pof |
Class 1 Drone (yellow) |
| robot01s.pof |
|
| robot08.pof |
?Class 3 Gopher Robot (white, drops mines/2 lasers) |
| robot09.pof |
Medium Hulk (brown) |
| robot09s.pof |
|
| robot16.pof |
?"Class 2 Platform Robot" (white, 2-body, laser/missile) |
| robot17.pof |
Medium Lifter (green, 2 arms) |
| robot17s.pof |
|
| robot22.pof |
?Spider (red, 4 legs) |
| robot22s.pof |
|
| robot23.pof |
?Class 2 Drone (2-body, blue) |
| robot23s.pof |
|
| robot26.pof |
? "Class 2 supervisor robot" (smaller ball) |
| robot27.pof |
?AI robot"Secondary Lifter" (red, 1 leg) |
| robot27s.pof |
|
| robot30.pof |
(Ball) |
| robot31.pof |
? (Red triangle) |
| robot32.pof |
?Baby spider (red, 2 legs) |
| robot32s.pof |
|
| robot35.pof |
?(ball-like, 2 arms) |
| robot35s.pof |
|
| robot37.pof |
?Class 1 Driller (Vulcan) |
| robot37s.pof |
|
| robot38.pof |
?Hulk-style "small hulk?" (green) |
| robot38s.pof |
|
| robot39.pof |
?"Advanced Lifter" (red, 4 arms) |
| robot39s.pof |
|
| robot40.pof |
?"PTMC Defence Prototype" (2-body, 4 lasers) |
| robot40s.pof |
|
| robot42.pof |
?"Class 1 Heavy Driller" (plasma-gun) |
| robot42s.pof |
|
| robot43.pof |
?boss-style? |
| smissile.pof |
|
It seems as if the file is build of several blocks, each
with a short header, typically 4 characters plus a 4 byte length of the rest of the block.
(All ints are little endian = Intel style)
All blocks have a 4 char header followed by 4 byte
length-of-data. For example:
47 55 4E 53 char4 Id = "GUNS"
02 00 00 00 int32 Length = 2 00 00 2 bytes of data
|
For experiments I use robot01.pof, which is the first robot
you encounter at level 1: "class 1 drone".
This is the POF-file identification and a header for the
entire file.
struct
{
char id[4]="PSPO"; //file header
int16 version; //file version
};
|
version=7 for boss01, boss02, exit01, exit01d,
fusion1, fusion2, laser11s, laser1-2, laser12s, laser21s, laser22s, laser31s, laser32s,
laser41s, laser42s, pship1, pship1b, pship1s, reactor, reactor2, robot01, robot01s,
robot08, robot09, robot09s, robot16, robot17, robot17s, robot22, robot22s, robot23,
robot23s, robot26, robot27, robot27s, robot30, robot31, robot32, robot32s, robot35,
robot35s, robot37, robot37s, robot38, robot38s, robot39, robot39s, robot40, robot40s,
robot42, robot42s, robot43
version=6 for cmissile, flare, laser1-1, laser2-1,
laser2-2, laser3-1, laser3-2, laser4-1, laser4-2, mmissile, smissile
Texture list for robot:
struct
{
int 16 strCount; //number of strings
char strings[strCount][8]; //8 char (including null) ASCIIZ strings, refer to textures in the PIG file.
}
|
Header for polymodel:
struct
{
int32 numModels //number of submodels
int32 modelRad //radius of model
vms_vector min //BSPTree bounds
vms_vector max //BSPTree bounds
}
|
This block is repeated a number of times. My current guess
is that each of these define a sub-object, e.g. robot01.pof has the following three
sub-objects: body, left arm, right arm.
Current guess:
struct
{
int16 subNum; //Submodel number
int16 parentNum; //Submodel parent
vms_vector subPlaneNorm; //Normal for submodel clip plane
vms_vector subPlanePnt; //Point on clip plane
vms_vector subOffset; //Offset of location in space
int32 modelRad; //Radius of model
int32 subPtr; //Offset in file to IDTA reference for this model
}
|
Gives info on guns for the model/bot:
int32 numGuns; //Number of guns
guns guns[numGuns];
struct guns
{
int16 gunID; //ID number of this gun
int16 gunSub; //Submodel this gun is attached to
vms_vector gunPoint; //Point where this gun starts
vms_vector fireVector; //Direction the gun fires
}
|
Animation states for model:
struct
{
int16 numFrames; //Number of different animation states
anim_angs[numframes][numModels]; //The list of anim angles for all models. numModels is number of models (see OHDR block).
}
|
The IDTA field consists of a number of structures,
identified by an int16 number. The structures may have variable length depending on the
data they store. It is the same structure as used in D2. Get informations about the IDTA
format here: