Files
ordoor/doc/formats/mnu.md
Nick Thomas 786d261f98 Allow dialogues to be hidden or shown
To do this, MENU and SUBMENU are split into two types (at last), and
a Widget type is introduced. This should allow lots of code to be
removed at some point.
2020-04-14 03:14:49 +01:00

283 lines
9.0 KiB
Markdown

# *.mnu
These files appear to be the UI definitions for Chaos Gate. Some relate to
system menus, other to in-game menus. Their names are hardcoded into the
`WH40K.exe` binary. Each has a `.obj` file associated with it.
It's an ASCII-formatted text file with a 12-line header, followed by a number
of descriptor records.
Here's the top of `MainGame.mnu`:
```
MainGame.obj
BACKGROUND COLOR 0..255..-1 trans : 0
HYPERTEXT COLOR 0..255 : 120
FONT TYPE 0..5 : 10
wh40k_12
basfnt12
wh40k_47
wh40k_12_red
wh40k_12_blue
wh40k_12_green
wh40k_12_yellow
NULL
```
The first line of the header is a `.obj` file containing sprites we want to
display on-screen. We see entries further down have a `SPRITEID`, which must
reference entries in that file.
In `SaveGame.mnu`, we can see multiple `.obj` files can be referenced.
There are then 3 lines that seem to be fixed descriptor names with values
that vary. Is this font colour, perhaps? Unsure.
Next is a variable-length list of font names, referencing files in the `Fonts`
directory.
Finally, there's a list of records that specify the menu itself. Truncated
contents of `SaveGame.mnu`:
```
#rem..........Background
MENUID : 1
MENUTYPE : 0
MOVEABLE : 0
ACTIVE : 1
SPRITEID : 0
ACCELERATOR: 0
DRAW TYPE : 0
SHARE : -1
X-CORD : -1
Y-CORD : -1
DESC :
*
#rem..........MAIN BACKGROUND
MENUID : 2
MENUTYPE : 45
MOVEABLE : 0
ACTIVE : 1
SPRITEID : 0
ACCELERATOR: 0
DRAW TYPE : 0
SHARE : -1
X-CORD : -1
Y-CORD : -1
DESC :
#rem.......... MAIN BACKGROUND
SUBMENUID : 1
SUBMENUTYPE: 31
FONTTYPE : 20
ACTIVE : 0
SPRITEID : -1
ACCELERATOR: 0
DRAW TYPE : 0
SHARE : 0
SOUNDTYPE : 0
DESC :
*
#rem..........Chat List Box Menu
MENUID : 21
MENUTYPE : 1
MOVEABLE : 0
ACTIVE : 1
SPRITEID : 764
ACCELERATOR: 0
DRAW TYPE : 0
SHARE : -1
X-CORD : -1
Y-CORD : -1
DESC :
[...]
*
~
```
We start processing these as soon as we see `MENUID`, I suppose. Each toplevel
item is `*`-delimited, and the list is terminated with `~`.
Each menu has a list of parameters:
| Name | Examples | Purpose |
|---------|----------|---------|
| `MENUID`| `1`, `2`, `3` | Maybe linking between menus? |
| `MENUTYPE` | `0`, `1`, `2`, `3`, `45`, `300` | ? |
| `MOVEABLE` | `0` | Unimplemented functionality? |
| `ACTIVE` | `0`, `1`, `1,0` | ? |
| `SPRITEID` | `-1`, `0`, `123`, `16,-1,1` | Select from `.obj` file? |
| `ACCELERATOR` | | ? |
| `DRAW TYPE` | | ? |
| `SHARE` | | ? |
| `X-CORD` | `-1`, `0`, `200` | X coordinate to draw at |
| `Y-CORD` | `-1`, `0`, `200` | Y coordinate to draw at |
| `FONTTYPE` | | Choose a font from the above? |
| `SOUNDTYPE` | | ? |
| `DESC` | `CHARACTER SELECT`, `51005` | Text, or reference to `Data/USEng.dta` |
Submenus also show a couple of unique values:
| Name | Examples | Purpose |
|---------------|---------------|---------------|
| `SUBMENUID` | `1`, `2`, `3` | As `MENUID` |
| `SUBMENUTYPE` | `0`, `1`, `2` | As `MENUTYPE` |
It seems .mnu files can also include other files, which have the extension
`.mni` (presumably for "Menu include"). Examples:
```
*
$GenDialog.mni
$GenLoad.mni
```
It looks like we just interpolate the named file into the text when we come
across one of these lines.
The `MENUID` in `GenDialog` and `GenLoad` is a 2-element list, like `1000,1`
or `2000,2`. The second number corresponds to the offset in the list of object
files.
## `MENUTYPE`
Here's the full list of values for `MENUTYPE`:
| Value | Meaning |
| ----- | ------------ |
| 0 | `Background` |
| 1 | `Menu` |
| 2 | `DragMenu` |
| 3 | `RadioMenu` ??? - only seen in `LevelPly` and `LoadGame` around select-one items |
| 45 | `MainBackground` ??? - only seen in `MainGame` and `MainGameChaos` |
| 300 | `Dialogue` |
The `MENUTYPE` acts as a logical grouping of a set of objects onscreen, and
gives strong hints about how to handle their children.
## `SUBMENUTYPE`
The types seem to refer to different types of UI widget. Here's a list of unique
values:
| Value | Meaning |
|-------|---------|
| 3 | `Button` |
| 30 | `DoorHotspot1` |
| 31 | `DoorHotspot2` |
| 40 | `LineKbd` |
| 41 | `LineBriefing` |
| 45 | `Thumb` |
| 50 | `InvokeButton` |
| 60 | `DoorHotspot3` |
| 61 | `Overlay` |
| 70 | `Hypertext` |
| 91 | `Checkbox` |
| 100 | `EditBox` |
| 110 | `InventorySelect` |
| 120 | `RadioButton` |
| 200 | `DropdownButton` |
| 205 | `ComboBoxItem` |
| 220 | `AnimationSample` |
| 221 | `AnimationHover` |
| 228 | `MainButton` |
| 232 | `Slider` |
| 233 | `StatusBar` |
| 400 | `ListBoxUp` |
| 405 | `ListBoxDown` |
`400`, `405`, and `45`, can all accept 4 values for `SUBMENUTYPE` in a
comma-separated list. These records combine to form a `TListBox` control, with a
number of visible slots that act as a viewport. There is a draggable vertical
slider (the "thumb") to show where in the full list the viewport is, and up +
down buttons to move the position of the thumb by one, so it's feasible that
these values tell us about the available steps.
Here are the values in `Briefing.mnu`:
```
#rem..........List Box Menu
MENUTYPE : 1 # List Box Menu
SUBMENUTYPE: 400,22,22,13 # Scroll Up
SUBMENUTYPE: 405,22,22,13 # Scroll Down
SUBMENUTYPE: 45, 14,15,13 # Thumb
```
There are 13 elements in this listbox, which sorts out the fourth number (but
what is it used for?). The other two need more investigation.
## Positioning
The X-CORD and Y-CORD values would seem to be related, to this, but they are
universally set to 0 or -1.
Far more important are the XOffset and YOffset values for each sprite in the
associated .obj files. Taking these into account is enough to draw `Options.mnu`
successfully, for instance:
![](img/Options.mnu.png)
However, it's *not* sufficient to put all the items for `MainGame.mnu` in the
right place.
## Animation
This seems to be done by choosing a different sprite to draw every N ticks. They
are laid out sequentially, but I don't yet know how to animate them. It's likely
to be the same approach as used for other obj files.
Looking at Main.mnu, it points at the object fail Main.obj. This has 118
sprites, which can be described as follows:
| Start | Count | Desc |
| ------ | ----- | ---- |
| 0 | 1 | Background image |
| 1 | 3 | New game button: base, pressed, disabled |
| 4 | 3 | Load game button: base, pressed, disabled |
| 7 | 3 | Multiplayer button: base, pressed, disabled |
| 10 | 3 | Settings button: base, pressed, disabled |
| 13 | 3 | Quit button: base, pressed, disabled |
| 16 | 20 | New game button: 20 animation frames |
| 36 | 20 | Load game button: 20 animation frames |
| 56 | 20 | Multiplayer button: 20 animation frames |
| 76 | 20 | Settings button: 20 animation frames |
| 96 | 20 | Quit button: 20 animation frames |
| 116 | 1 | Section of background ("Menu title") |
| 117 | 1 | Version hotspot |
So we have 5 buttons with very similar characteristics, but at different sprite
offsets, and two distinct ranges per button, plus some others. Here's some
attributes plucked from `Main.mnu`:
| Name | (SUB)MENUTYPE | "Active" | "SPRITEID" | "DRAW TYPE" | "SHARE" |
| ---------- | ------------- | -------- | ---------- | ----------- | ------- |
| Background | 1 | 1 | 0 | 0 | -1 |
| Start menu | 1 | 1 | -1 | 0 | -1 |
| New game | 228 | 1,0 | 16,-1,1 | 20 | 1 |
| Load game | 228 | 1,0 | 36,-1,4 | 20 | 4 |
| MP game | 228 | 1,0 | 56,-1,7 | 20 | 7 |
| Options | 228 | 1,0 | 76,-1,10 | 20 | 10 |
| Quit | 228 | 1,0 | 96,-1,13 | 20 | 13 |
| Menu title | 61 | 1 | -1 | 0 | 116 |
| V hotspot | 61 | 1 | -1 | 0 | 117 |
The buttons, menu title and version hotspot are submenus of the start menu.
### `ACTIVE`
There are only 4 values seen across all menus: `0`, `1`, `1,0`, `102` and `1,1`.
Perhaps this represents possible states?
### Sprite selection
For the background (`MENUTYPE: 1`), this points simply at the sprite index in
the object file. For the start menu, it's `-1` (no sprite, I assume). For the
menu title and version hotspot (`MENUTYPE: 61`, it's `-1` too.
For the buttons, it's a list pointing to the start of the 20 animated frames,
`-1`, then the start of the 3 static frames.
`DRAW TYPE` is the number of animated frames. We only use the animated frames
when the button is focused. `SHARE` repeats the start of the static frames, and
is the only place they're found for the menu title and version hotspot.