Daggerfall Mod:WOODS.WLD format
This is a description of the format of the WOODS.WLD file found in the ARENA2 directory of Elder Scrolls: Daggerfall by Bethesda. The information here is not complete or 100% accurate, although the basic format appears to be well understood.
Contents
Header[edit]
The first 0x90 (144) bytes of the file are composed of a Header structure.
Offset | Type | Name | Description |
---|---|---|---|
0-3 | UInt32 | OffsetSize | This is the size of the offset list which immediately follows the header. Since each element is 4 bytes long, ( Width * Height ) should equal ( OffsetSize ÷ 4 ). |
4-7 | UInt32 | Width | This indicates the width of the Elevation Map. This should be 1000. |
8-11 | UInt32 | Height | This indicates the height of the Elevation Map. This should be 500. |
12-15 | UInt32 | NullValue1 | This value should be 0x00000000. |
16-19 | UInt32 | DataSectionOneOffset | This is the offset to the Data Section 1 section, relative to the start of the file. |
20-23 | UInt32 | Constant1 | Should be 1 (0x1). Does not appear to have any impact on the game. |
24-27 | UInt32 | Constant2 | Should be 22 (0x16). Does not appear to have any impact on the game. |
28-31 | UInt32 | ElevationMapOffset | This is the offset to the Elevation Map section, relative to the start of the file. |
32-143 | UInt32[ 28 ] | NullValue2 | Each element of this array should be 0x00000000. |
Data Offsets[edit]
Immediately following the Header, is a contiguous list of UInt32 values. There should be Header.Width * Header.Height (500000) elements. Each element is an offset (relative to the start of the file) to a PixelData structure. Each element corresponds by ordinal to an Elevation Map element; that is to say the tenth offset in this contiguous list describes the tenth pixel in the Elevation Map array. Daggerfall expects these elements to be stored in left-to-right, top-to-bottom order. Editors should follow this convention. This does not mean element n must specify a disk location which precedes n+1; it merely means element n specifies a row which is "above" row n+1 in the output bitmap.
Terrain Types[edit]
This section contains 256 different TerrainParameter structs. These control terrain generation parameters, which one to apply for a given map pixel is selected by the TerrainType value in the PixelData struct. The section is 1024 bytes in size (0x0400).
Offset | Type | Name | Description |
---|---|---|---|
0 | UInt8 | Clamp Height | The height that Daggerfall clamps low lying areas to. By default this is ocean level. Note that Daggerfall does not simply clamp all terrain below a certain height, instead it seems to incorporate some noise as well. |
1 | UInt8 | Clamp Sensitivity | How aggressively Daggerfall clamps terrain, the higher this is the higher areas will be clamped to ClampHeight. |
2 | UInt8 | Unknown | Unknown Purpose, appears to affect terrain texturing. |
3 | UInt8 | Unknown | Unknown Purpose, appears to affect terrain texturing. |
Elevation Map[edit]
This does not appear to be used by the game. Instead the ElevationNoise in the PixelData structures is used to determine terrain elevation.
As the name suggests, this section contains elevation data for a small, 1000x500 pixel, map of the Iliac Bay. Each byte represents one pixel, with Header.Width * Header.Height pixels in total. Low values are low elevations, high values are high elevations, with 0x00 through 0x02 considered water. There are no pixels with an elevation of 0x03.
Each pixel is represented by a signed 8 bit integer, however values below 0 are invalid and will crash the game. This gives a range of permissible values of 0-127.
The values are stored in left-to-right, top-to-bottom order. That is to say the first 1000 elements describe the first (top-most) row of the map, and the second 1000 elements describe the second row of the map, and so on.
Pixel Data[edit]
For each of the pixels in the Elevation Map, there is a corresponding PixelData element (0x2F, 47 bytes in size). Offsets to each PixelData structure is found immediately following the Header as a contiguous list of UInt32 offsets.
Offset | Type | Name | Description |
---|---|---|---|
0-1 | UInt16 | Unknown1 | Unknown Purpose. |
2-5 | UInt32 | NullValue1 | Always 0x00000000. |
6-7 | UInt16 | FileIndex | Valid values are defined by the FileIndex Enumeration, below. |
8 | UInt8 | TerrainType | Selects one of the 256 terrain types, which control terrain generation parameters. |
9 | UInt8 | TerrainNoise | Controls the amount of high frequency noise on the terrain. Observed values are {0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0}. (IIRC some values crash the game, try to stick to values already in use) |
10-21 | UInt32[ 3 ] | NullValue2 | Each element is always 0x00000000. |
22-46 | Int8[ 5 ][ 5 ] | ElevationNoise | Each signed byte element of this two-dimensional array provides noise for the pixel's Elevation field, thus giving the overland hills, valleys, etc. For some reason the resultant 5000x2500 pixel map has a strange grid-like pattern imposed on it by this field. The ElevationNoise elements are stored in left-to-right, top-to-bottom order. |
FileIndex Enumeration[edit]
The FileIndex enumeration does not identify the texture file to use when displaying the ground for that specific map pixel. It is a decoy. This data is actually in CLIMATE.PAK.
Value | Description | Texture File |
---|---|---|
2 | Desert | TEXTURE.002 |
102 | Mountain | TEXTURE.102 |
302 | Temperate | TEXTURE.302 |
402 | Jungle | TEXTURE.402 |
Working with WOODS.WLD[edit]
Everything one needs to create the Iliac Bay in a 3D environment, such as DirectX or OpenGL, is present.
Building the Map[edit]
One can use the data present in WOODS.WLD to generate an almost complete map for the Iliac Bay. This documentation will assume the standard 3D coordinate format of (X, Y, Z), where X represents the east-west axis, Y represents the elevation axis, and Z represents the north-south axis. Daggerfall World Units are proportionate to the United States Inch, and the valid domain for each axis is defined as: Dom(X) ≡ (51200, 32753664), Dom(Y) ≡ (-80, 1228), and Dom(Z) ≡ (16384, 16367616).
First one reads the ElevationMap to retrieve the base elevation for the location. Each element within the ElevationMap refers to a PixelData element, so one must then next read the PixelData. One then adds to each element of the PixelData.ElevationNoise array the value reported by the pixel's corresponding entry in the ElevationMap. One now has the base elevation for every location within the game.
The next step is a matter of scaling. Each pixel in this resultant 5000 x 2500 bitmap equal to 6467.584 inches by 6516.736 inches. This places the Iliac Bay's total area at 135240.22691037170846039793070852 square miles (between California and Nevada in total size, with the defined land area about 1.6 times that of England).
Adding Locations[edit]
To determine which of these map pixels a Location from MAPS.BSA (or the player's character for that matter) occupies one must simply translate from Daggerfall World Units to the above Map Units.
First, one must subtract 51200 from the location's X coordinate, and 16384 from the location's Y coordinate. The next step is then to divide the X coordinate by 32702.464 and divide the Y coordinate by 32702.464. One now has the specific pixel location in 1000x500 scale.
At this point one has the location for the lower-left corner of the location's first Block, as defined by the location's ExteriorData Block* arrays. Blocks are stored in west-to-east, south-to-north order. Each Block has a uniform size.
Textures[edit]
The specific textures to load for the ground planes, the flats, and the structures is determined by the CLIMATE.PAK file.