zeh@Posted: Sat Sep 04, 2004 6:26 pm :
Welcome back to lesson number seven in the GUI scripting series.

In this tutorial we'll assemble the first parts of our new HUD, and we'll deal with the most basic types of interaction between the HUD system and the game itself. Since I'm splitting these HUD tutorials in several mini-lessons, this one will only cover the primary on-screen items.

Complete GUI Scripting - 7: Creating basic HUD items

We're now ready to take a step further and make our HUD actually work. While the previous lesson was just a mini-tutorial on getting an empty HUD script file ready, now we'll add real content to our customized HUD.

Like I said on the previous lesson, we'll build a custom HUD script based on nothing less than the classic DOOM 1 HUD. Let's have a look at it.

Image
Image from idsoftware.com

It's pretty much straightforward: there's a bar at the bottom showing how much ammo the player has left, his health, the guns he have available, his actual state (by using his face), his armor, the keys he have available, and the amount of ammo he has left for all kinds of guns.

In this lesson (and on the next ones), we'll create this HUD from scratch. What we will implement is:

What we will not implement however, is:

It's important to notice, however, that this is just an example of basic HUD situations and even though some of the elements from the classic HUD will be out, this tutorial will be complete in essence.

Ok, time to get down to business. Open up the HUD script we created on the last lesson, and delete everything there. As the previous script was just a test, we'll create a new one now. Let's use this code for a start.

Code:
windowDef Desktop {
   rect   0,0,640,480
   visible   1
   noevents   1
   nocursor  1
}


Ok, this creates our main windowDef. The most important thing to notice is that we're using the "nocursor 1" property -- since this is not a GUI that the player will actually interact with, this is important so a dead mouse cursor won't show.

Fire up DOOM 3 using the command-line arguments for our HUD testing as mentioned in the previous lesson, and we're ready to switch between the editor and the game to test our HUD.

Code:
<your doom 3 folder>\Doom3.exe +seta r_mode 3 +set r_fullscreen 0 +set fs_game classichud +map game/mp/d3dm1


We're now ready to add graphic assets to the HUD. Now, when creating a HUD (or any GUI script for that matter) on a specific MOD, you have to adopt some standard location from files. While there isn't any specific path you have to use, it's important to use some paths that make sense for you and for your MOD team (if you're working on a group), so things won't get chaotic (of course, if you're overwriting the original game assets, you have an specific path and filename you have to use, but that's not the case with our HUD graphics, just with the HUD script itself).

In this lesson's case, I've decided to put all GUI assets for our MOD/HUD on the <doom 3>/classichud/guis/assets folder. So create this directory, grab the example files at the end of this article, and unpack all images there.

The images we'll use were created straight from the original DOOM shareware doom1.wad file, and from some screenshots I found on google. This is an scripting tutorial, so we won't worry about creating the graphics; we'll just use the original ones and that's that.

Okey. Now, with the images unpacked at <doom 3>/classichud/guis/assets, we'll add one of the most basic items from our HUD, the bottom bar.

Code:
windowDef Desktop {
   rect   0,0,640,480
   visible   1
   noevents   1
   nocursor  1

//=============================================================================
// Main bar
//=============================================================================

   windowDef base {
      rect   0,416,1024,64
      visible   1
      background   "guis/assets/hud_base"
      matcolor   1,1,1,1
   }

}


So we just added an static graphic at the bottom. Pretty simple. Of course, the lines starting with "//" are just comment lines that can be omitted; they have been added for ease of read only.

Getting back to the windowed game and doing our reloadguis command will show our progress so far.

Image

Getting down to business, let's start adding the basic HUD fields: first, the health.

Code:
windowDef Desktop {
   rect   0,0,640,480
   visible   1
   noevents   1
   nocursor  1

//=============================================================================
// Main bar
//=============================================================================

   windowDef base {
      rect   0,416,1024,64
      visible   1
      background   "guis/assets/hud_base"
      matcolor   1,1,1,1
   }

//-----------------------------------------------------------------------------
// Standard indications: ammo, armor, health
//-----------------------------------------------------------------------------

   windowDef bar_health {
      rect   110,420,60,49
      visible   1
      forecolor   1,1,1,1
      text   "gui::player_health"
      textscale   0.6
      textalign   2
      font   "fonts/english"
   }

}


Here's something interesting. You'll notice that, on the text property of the HUD script, instead of using an static string, we used a reference to a variable -- "gui::player_health". This is something new on these GUI scripting tutorials in two aspects.

First, it's a "hard-coded" variable from the GUI scripting system -- "player_health". The GUI system has several variables that can be used to read the player health, ammo, and lots of other stuff, and "player_health" is one of them. So, "gui::<variable name>" is the right way to refer to those variables.

Second, since it's a variable, it's passed as a reference, not as a value. It means that instead of just reading the value when it starts, the GUI system will update the "text" property when that variable changes. So whenever "gui::player_health" changes, the text property of that windowDef will change, updating the health.

Now, getting back to game again, and reload the guis, let's see how it works.

Image

And, if we take damage...

Image

Fine. This isn't quite like the original, though; the font is wrong, and there's no "%" in the value caption.

While we can't add our custom fonts just yet, we can add the "%" value already. We can't do that by transforming the text property of the windowDef, or by concatenating any string -- the GUI system doesn't allow such 'powerful' features. We'll have to do a little hack by adding a new windowDef with the "%" text. So it gets us down to,

Code:
(...strip...)

//-----------------------------------------------------------------------------
// Standard indications: ammo, armor, health
//-----------------------------------------------------------------------------

   windowDef bar_health {
      rect   110,420,60,49
      visible   1
      forecolor   1,1,1,1
      text   "gui::player_health"
      textscale   0.6
      textalign   2
      font   "fonts/english"
   }
   windowDef bar_health_percent {
      rect   170,420,40,49
      visible   1
      forecolor   1,1,1,1
      text   "%"
      textscale   0.6
      textalign   0
      font   "fonts/english"
   }
}


Notice I've cut out part of the code, or else our source code will start to get bigger and bigger and difficult to read what has actually changed.

So, I just added the "bar_health_percent" windowDef. Checking results again...

Image

Fine. Let's do the same with the armor and ammo fields. It's kind of lengthy but pretty simple.

Code:
(...strip...)

//-----------------------------------------------------------------------------
// Standard indications: ammo, armor, health
//-----------------------------------------------------------------------------

   windowDef bar_health {
      rect   110,420,60,49
      visible   1
      forecolor   1,1,1,1
      text   "gui::player_health"
      textscale   0.6
      textalign   2
      font   "fonts/english"
   }
   windowDef bar_health_percent {
      rect   170,420,40,49
      visible   1
      forecolor   1,1,1,1
      text   "%"
      textscale   0.6
      textalign   0
      font   "fonts/english"
   }
   windowDef bar_armor {
      rect   370,420,60,49
      visible   1
      forecolor   1,1,1,1
      text   "gui::player_armor"
      textscale   0.6
      textalign   2
      font   "fonts/english"
   }
   windowDef bar_armor_percent {
      rect   430,420,40,49
      visible   1
      forecolor   1,1,1,1
      text   "%"
      textscale   0.6
      textalign   0
      font   "fonts/english"
   }
   windowDef bar_ammo {
      rect   15,420,60,49
      visible   1
      forecolor   1,1,1,1
      text   "gui::player_ammo"
      textscale   0.6
      textalign   2
      font   "fonts/english"
   }

}


Pretty much the same thing applies to these new windowDefs - using the "gui::player_ammo" and "gui::player_armor" variables, we can retrieve the values of the user ammo and armor, respectively.

Image

Nice, we're getting there. Now, we'll add the weapon numbers, right after those health/armor/ammo windowDefs.

Code:
(...strip...)

//-----------------------------------------------------------------------------
// Weapon numbers
//-----------------------------------------------------------------------------

   windowDef gun_2 {
      rect   218, 416, 40, 40
      visible   1
      forecolor   1,1,0,1
      text   "2"
      textscale   0.25
      font   "fonts/micro"
   }

   windowDef gun_3 {
      rect   242, 416, 40, 40
      visible   1
      forecolor   1,1,1,0.4
      text   "3"
      textscale   0.25
      font   "fonts/micro"
   }

   windowDef gun_4 {
      rect   266, 416, 40, 40
      visible   1
      forecolor   1,1,1,0.4
      text   "4"
      textscale   0.25
      font   "fonts/micro"
   }

   windowDef gun_5 {
      rect   218, 436, 40, 40
      visible   1
      forecolor   1,1,1,0.4
      text   "5"
      textscale   0.25
      font   "fonts/micro"
   }

   windowDef gun_6 {
      rect   242, 436, 40, 40
      visible   1
      forecolor   1,1,1,0.4
      text   "6"
      textscale   0.25
      font   "fonts/micro"
   }

   windowDef gun_7 {
      rect   266, 436, 40, 40
      visible   1
      forecolor   1,1,1,0.4
      text   "7"
      textscale   0.25
      font   "fonts/micro"
   }

}


You'll notice most of the weapons have a "forecolor" property of "1,1,1,0.4" - that is, 40% black. The first one, though, has a forecolor of "1,1,0,1" - yellow. That's because we have already picked it up; we'll make the weapon numbers turn to yellow as guns are picked up.

Well, let's check the progress for now.

Image

Okey. Now, to finally add the marine face..

Code:
(...strip...)

//=============================================================================
// Marine faces
//=============================================================================

//-----------------------------------------------------------------------------
// Normal face
//-----------------------------------------------------------------------------

   windowDef marineFace {
      rect   290,418,64,64
      visible   1
      background   "guis/assets/hud_face_100_center"
      matcolor   1,1,1,1
   }

}


And testing...

Image

Looking good.

Well, this is it for adding basic HUD functionalities. On the next lessons, we'll make the marine face act accordingly to what's happening, and make the weapon numbers update. See you there.

Download source and example files (8kb)



rich_is_bored@Posted: Sat Sep 04, 2004 7:03 pm :
Very nice zeh. :)



MNeMiC@Posted: Sat Sep 04, 2004 8:41 pm :
Ya! Y'0 be deffinitly the man! man!



b0ksah@Posted: Mon Sep 06, 2004 6:32 pm :
hehe very nicely done :)

*bump*



evilartist@Posted: Sat Dec 04, 2004 5:32 am :
Great tutorial zeh!

I have just one question: how can I show the weapon's ammo TOTAL?

You showed us how to display the current weapon's ammo in that current magazine/clip, but you can't see the total ammo carried. A little help, please?



zeh@Posted: Sat Dec 04, 2004 11:55 am :
evilartist wrote:
Great tutorial zeh!

I have just one question: how can I show the weapon's ammo TOTAL?

You showed us how to display the current weapon's ammo in that current magazine/clip, but you can't see the total ammo carried. A little help, please?


Evilartist, that'd dependend on weapon, and on the variables created. The one I used, gui::player_ammo, should have the current ammo of the weapon, but now that you mention it, on weapons that need reload, it might indicate the current clip instead of the total availabel ammo, I haven't tested that part. In this case, I think gui::player_totalammo would be the correct one.



RitchieTheBrit@Posted: Tue Apr 17, 2007 3:06 pm :
Just in case anyone can't find the shareware copy of Doom, it's still available from iD's FTP server HERE.

Just thought I would throw that out there for anyone else wanting to follow the tutorial.



shadowscrawl@Posted: Mon Jul 27, 2009 7:41 pm :
hi i have a question

i am working on my own remake of the doom hud (though slightly enhanced to work better with doom 3 and for graphical improvement) and i am trying to implement in place of the old ammo counter a graphic of whatever gun is currently selected (like old school wolfenstein)

i want the "current" section (see picture below) to display an icon of whatever weapon is currently selected

i have experimented and experimented and i feel i have gotten close a few times but i just cant make it work so i give in and humbly throw myself to one much smarter then i

any help you can provide would be great

Image