Rearranging the status bar

In Wolfenstein 3D, the status bar is a static image, over which the stats pertaining to the player and game are displayed.

The Wolf3D status bar

Of course, in a different project, this design might not be relevant. Maybe the game has more than 4 keys, or the author doesn't want to display weapons, or simply wants things in different places.

That's when deeper changes are required. In DOS and Wolf4SDL, some tinkering with the source code is necessary. In ECWolf/LZWolf, some scripting can be done to achieve the same effect. In the end, both are simple endeavours once you understand what needs to be done.

All the elements overlaying the status bar - the numbers, player's face, current weapon. These elements are called using a function called StatusDrawPic(), formatted as follows:

StatusDrawPic (unsigned x, unsigned y, unsigned picnum);

In WL_AGENT, we can scroll down to the DrawWeapon and DrawKeys functions to see it being used.

/*
==================
=
= DrawWeapon
=
==================
*/

void DrawWeapon (void)
{
    if(viewsize == 21 && ingame) return;            // This line is part of Wolf4SDL, and may not be present in your source code
    StatusDrawPic (32,8,KNIFEPIC+gamestate.weapon);
}


/*
==================
=
= DrawKeys
=
==================
*/

void DrawKeys (void)
{
    if(viewsize == 21 && ingame) return;        // This line is part of Wolf4SDL, and may not be present in your source code
    if (gamestate.keys & 1)
        StatusDrawPic (30,4,GOLDKEYPIC);
    else
        StatusDrawPic (30,4,NOKEYPIC);

    if (gamestate.keys & 2)
        StatusDrawPic (30,20,SILVERKEYPIC);
    else
        StatusDrawPic (30,20,NOKEYPIC);
}

StatusDrawPic() asks for 3 variables. The first and second are each the x and y coordinates on the status bar, and the third is the image to be displayed from the VGAGRAPH file.

In the above example, DrawWeapon() is drawing an image at the co-ordinates (32,8) relevant to the player's current weapon. It will default to KNIFEPIC, then add the value of the weapon (Knife is 0, Pistol is 1, Machinegun is 3, etc). As the relevant weapon images are grouped sequentially in the game files, it will add the value of the weapon and get to the correct image.
In DrawKeys(), the image that is displayed is dictated by the values of gamestate.keys. If the player has the gold key, it will display GOLDKEYPIC, and the same goes for the silver key. However if a key isn't collected, it will display a blank image (NOKEYPIC) at the same coordinates instead.

While everything on the status bar is handled with images, numbers have to be handled slightly differently. This is because each digit of a number is an individual image, and the game needs to know how many instances of StatusDrawPic() to create and group, and of which numbers.

To cover this, we have the LatchNumber() function. This function does all the hard lifting of managing the numbers side of things, and is set out as follows

LatchNumber (int x, int y, unsigned width, int32_t number);

We can see it in use within a function like DrawHealth(), which will update the amount of health shown on the status bar.

/*
===============
=
= DrawHealth
=
===============
*/

void DrawHealth (void)
{
    if(viewsize == 21 && ingame) return;        // This line is part of Wolf4SDL, and may not be present in your source code
    LatchNumber (21,16,3,gamestate.health);
}

We can see here that it is calling on LatchNumber, with four variables.

The first two variables are the x and y coordinates, telling the game where on the status bar we should be printing.
The third variable represents the maximum number of digits to display. In regards to health, the player can reach a maximum of 100, which is 3 digits long ( 1 | 0 | 0 ). As such, this variable is 3.
The final and most important variable is telling LatchNumber what to display. In this function, it is calling to display the amount of health the player currently has.

By default, Wolfenstein 3D displays the player's score up to a value of 999,999, a limitation that might not necessarily work for all modding projects.

We can see the code for DrawScore() in WL_AGENT:

/*
===============
=
= DrawScore
=
===============
*/

void DrawScore (void)
{
    if(viewsize == 21 && ingame) return;
    LatchNumber (6,16,6,gamestate.score);
}

What change needs to be made to this code to allow for up to 9,999,999 points to be displayed?

/*
===============
=
= DrawScore
=
===============
*/

void DrawScore (void)
{
    if(viewsize == 21 && ingame) return;
    LatchNumber (6,16,7,gamestate.score);
}

The third variable in LatchNumber is the amount of digits to be displayed for the number. Since 9,999,999 is 7 digits long ( 9 | 9 | 9 | 9 | 9 | 9 | 9 ), we change that number to 7.
You may also need to adjust the x and y co-ordinates to make sure the new amount of numbers fits in the area set aside for the score.

ECWolf and LZWolf modding is handled differently to classic Wolf3D modding, utilizing the editor SLADE to create a .pk3 file with the contents of the mod in it. Instead of editing the source code, text files containing scripting are put inside the .pk3 to be run by the game.

In these engines, the position and display of the status bar and items on it is handled within one of the files inside a pk3. This part of the guide assumes you already know the basics of setting up and modding an ECWolf project in SLADE.

This step could become redundant in future, when ECWolf updates to handle the status bar differently. For now (As of 2023) though, this is the way to do it.

Inside of your .pk3 file, create a new text file called latchcfg.txt. This file will handle variables similar to the way LatchNumber() works in DOS/Wolf4SDL.

The variables that can be adjusted are as follows

// Ammo
ammoenabled
ammodigits
ammox
ammoy

// Current Floor
floorenabled
floordigits
floorx  
floory

// Health
healthenabled
healthdigits
healthx
healthy

// Keys
keysx 
keysy

// Lives
livesenabled
livesdigits
livesx
livesy

// BJ's Face
mugshotx
mugshoty

// Score
scoreenabled
scoredigits
scorex
scorey

// Current Weapon
weaponx
weapony

// Items (As used in Super 3D Noah's Ark, and Mac Wolf3D)
itemsenabled
itemsdigits
itemsx
itemsy

Each set of variables works with a specific element of the status bar, and generally will cover four things:

  • enabled - Whether or not the particular element is shown. 1 means enabled, 0 means disabled. Example: livesenabled = 0 would disable the display of lives.
  • digits - How many digits of the number to display.
  • - The horizontal co-ordinate that the element will be displayed.
  • - The vertical co-ordinate that the element will be displayed.

Each variable will take a numerical input to know what to do. If it is not included in your mod's latchcfg.txt, then the default game's setting will be used.

An example of the numerical inputs, for displaying ammo:

ammoenabled = 1 // Enables ammo. 0 would hide it (Though it is still tracked)
ammodigits = 2 // 2 will display ammo up to 99, 3 will show 999, etc.
ammox = 27 // Sets the horizontal co-ordinate for ammo to 27, the default for Wolf3D.
ammoy = 16 // Sets the vertical co-ordinate for ammo to 16, the default for Wolf3D.

If that were your latchcfg.txt file in your pk3, you could do something like disable the display of the current level by simple adding a line as follows

ammoenabled = 1 // Enables ammo. 0 would hide it (Though it is still tracked)
ammodigits = 2 // 2 will display ammo up to 99, 3 will show 999, etc.
ammox = 27 // Sets the horizontal co-ordinate for ammo to 27, the default for Wolf3D.
ammoy = 16 // Sets the vertical co-ordinate for ammo to 16, the default for Wolf3D.

floorenabled = 0 // This will hide the display showing the current level.

ECWolf reads these files to see what has changed, and will automatically use defaults for anything not specified (Depending on the game the mod is being run through)