goliathvt@Posted: Wed Aug 11, 2004 4:11 am :
Okay, here's the situation: I wanted to be able to create a HUD using custom data. Right now, all that is listed in the hud.gui are gui parms that relate to the player: gui::player_health, gui::player_ammo, etc.

So, what happens if you want to display some dynamic data, say some information that you get from a level script, on your HUD?

Note that before you attempt any changes to your hud.gui... I've created a custom HUD in a mod directory... that is, I'm using +set fs_game MOD so that I don't make any changes to my vanilla game's HUD. If you want to muck around with changing your HUD, I highly recommend using +set fs_game too, so you don't mistakenly foobar your Doom3 HUD. You have been warned.

Okay, with that out of the way, let me describe my setup:

I had created a level script that counted the number of times a moveable entity hit the ground. I tracked this number using the technique written about here:

http://www.doom3world.org/phpbb2/viewtopic.php?p=31028

In that post, I basically just describe how to detect when a moveable object hits a trigger, and when the trigger activates, it calls a level script function.

So in this particular case, the script just counts the number of times a moveable ball object hits the floor. I then store that information into my ball entity as a key/value that I can easily retrieve at a later time.

Using that information, I then wanted to plug the number of times my ball object contacts the floor into my HUD and have it update dynamically. To do this, I had to make a few changes to my map:

1. I renamed the info_player_start entity so I could easily reference it in a script...

2. I added a key/value pair to my player entity:
Key: hitcount
Value: 0

3. I explicitely defined the GUI in the info_player_start entity...

EDIT: As in:

Key: gui
Value: guis/hud.gui

on the info_player_start entity.
/EDIT

This step is what allows you to reference gui parms with your player... without it, any key/value pairs you try to update via scripts won't change on the HUD. I imagine there's a more elegant way to get around this issue, but I haven't found it yet. On the other hand, if you were doing this for any other GUI, this step would be required... after all, without it, Doom3 doesn't know what GUI to apply to your object....

With those changes, let's move on to the scripts:

Here's a cut-down version of my level script (leaving out parts that don't pertain to this topic (and note that this script is far from polished!)). Also note that the myfloorhits() function is only about 5 lines of actual code... I've just added comments so you can tell what each statement does:

tt1.script:
Code:
// collision detection and script-to-HUD level script test

void setup_objects() {

   // empty
}

void myfloorhit() {

   // init hit counter var
   float hc = 0; // script hit counter

   // The number of hits gets stored into the ball entity
   // each time the function is called...
   // So we start by copying the value of our ballhits entity key
   // into the hit counter variable so that we can add to
   // the previous value
   hc = $myspball.getIntKey("ballhits");
   
   // since this function only gets called when the ball hits
   // the target area, we can increase the value of hits now
   hc++;

   // SET GUI PARM
   // This is the meat of our script-to-GUI interaction...
   // all we're doing is setting the a GUI parameter to
   // the current hit count value. 
   //
   // Since we want to update the player's hud, we've renamed the
   // info_player_start entity to:
   //
   // "spplayer"
   //
   // and added a key called:
   //
   // "hitcount"
   //
   // with an initial value of 0.
   //
   // That allows the use of the setGuiParm() function with
   // our player's HUD...
   //
   // Basically, just store the value of the "hc" script
   // variable into the GUI parm "hitcount"
   $spplayer.setGuiParm( "hitcount", hc );

   // now store the hit count value back into the ball entity
   // using our "ballhits" key so that it will be available the
   // next time the function gets called...
   $myspball.setKey("ballhits", hc);

// END   
}

void initfloorhits() {

   // initialize the GUI parm
   $spplayer.setGuiParm( "hitcount", 0 );
}

void main() {

   initfloorhits();

}


And here's the GUI:

hud.gui (make sure you don't overwrite your vanilla game's HUD)

Code:
// A custom player hud

windowDef Desktop {

   rect   0 ,0 ,640 ,480
   backcolor   0 ,0 ,0 ,0
   visible   1
   nocursor   1

   onEvent {
      // on any event, update the HUD hit count text string
      // with the gui parm "hitcount"
      //
      // "hitcount" is passed via a level script using
      // the setParm() function.
      //
      // Note: To access a GUI parm, you use:
      // "gui::xxxxx", where xxxxx is the
      // entity key passed by the setParm
      // script function...
      set "hitcountText::text" "gui::hitcount"
   }

   // "Floor Hits:" text
   windowDef HitsText {
      rect   3,377,131,36
      visible   1
      nocursor   1
      forecolor   1,1,0,1
      text   "Floor Hits:"
      textscale   0.5
      nowrap   1
      noevents   1
   }

   // Dynamic script data:
   windowDef hitCountText {
      rect   137,376,65,38
      visible   1
      nocursor   1
      forecolor 1,1,0,1
      text "blah blah" // this will be overwritten by the level script
      textscale   0.5
      nowrap   1
      noevents   1
      
   }

   // Version info text
   windowDef versionInfo {
      rect   3,445,159,31
      visible   1
      noevents   1
      nocursor   1
      forecolor   1,1,1,1
      text   "Balloon Bop/ Smash Ball\nv0.1"
      textscale   0.2
      backcolor   0,0.25098041,0.50196081,0.71764708
      bordersize   1
      bordercolor   1,1,0,1
   }
}


So that's one way to get level script variable data into a custom HUD. This will, of course, also work for any GUI by simply changing the entity named for the setParm() function and updating the gui key's value for your GUI entity with whatever gui script file and custom data you choose.

HUD - 0 Hits
Image

HUD - 3 Hits
Image

Hope this helps some folks.

Goliath



bullet@Posted: Wed Aug 11, 2004 4:53 am :
Excellent! This is getting bookmarked. Definitely something that will come in handy later :D



BNA!@Posted: Wed Aug 11, 2004 6:30 am :
Great!



CraiZE@Posted: Wed Aug 11, 2004 12:11 pm :
Absolutely awesome!



Eggy@Posted: Wed Aug 11, 2004 12:34 pm :
wp goli long live minigames eh? :p



goliathvt@Posted: Wed Aug 11, 2004 1:42 pm :
Mini games? Actually this is an essential part of my mod.

:)

G



zeh@Posted: Thu Aug 12, 2004 12:03 pm :
Awesome, I can't wait to start playing with this and your post will be a great help. Thanks.



Dingo_aus@Posted: Thu Jan 27, 2005 1:26 pm :
This tutorial has really helped me out, thank you



james102@Posted: Thu Apr 14, 2005 8:11 pm :
*bing* resurrection of old thread alert...

I've been trying to get this working, but instead of a custom hud, I'm trying to do it with a custom PDA.

I've checked and double checked, and while the hud variant seems to work, using the player_start, I can't get it going with a pda. Here's the setup:

There is an info_pda waiting to be picked up infront of the player, called "pda". It has been given the key/value of "gui" "gui/pda.gui". Picks up fine, it shows the custom pda, but the single bit of text that should be generated by the map script is not appearing, it's blank.

here's the relevent bit of pda.gui
Code:
onEvent{
      set "btnTheme1::text" "gui::foo"
   }

   windowDef pageThemes
   {
      rect   8,85,620,370
      visible   0
      bordersize   2
      bordercolor   0,0.25098041,0.50196081,1
      windowDef btnTheme1
      {
         rect   7,8,139,20
         visible   1
         backcolor   0,0.50196081,1,0.80000007
         text   "overwrite me"
         textscale   0.2
         forecolor   1,1,1,1
         bordersize   2
         bordercolor   0,0.25098041,0.50196081,1
         nowrap   1
      }
etc...etc...


and the snippet from the map script
Code:
void initPda(){
   $pda.setGuiParm("foo", "bar");
}

void main()
{
   initPda();
}


If anyone has any ideas, please share, because I am completely stumped.



Grimm@Posted: Thu Apr 14, 2005 9:20 pm :
Good stuuf, this shuould get stickied



james102@Posted: Thu Apr 14, 2005 9:32 pm :
ok I'm confused as hell now.
I go away to grab some coffee and clear my head (had been working for about 12 hours solid), and think "hmm, maybe the onEvent isn't happening, let's see what happens when you put set "btnTheme1::text" "gui::foo" in the onAction section of the btnTheme1 windowDef...

and it works...before clicking on it... I remove the line from onAction, and it still works. My brain is so very broken right now. But either way, kudos to goliath for coming up with this in the first place. :D

edit: just figured it out. I closed the editor, thus closed D3, and when I started again, I reloaded everything. I guess guis get loaded on game-launch, rather than on map-load.



Cody64@Posted: Fri Jun 03, 2005 4:28 am :
I cannot make this work with weapon scripts..... I'm trying to make the hud.gui display data from weapon scripts. I'm doing this to show what Fire Mode the current weapon is set to (if you've played my mod, you'll know what I'm talking about). Here is what I have:

Snippet of code from pistol.script:

Code:
setGuiParm( "mode", "Semi" );


And here is my code from hud.gui:

Code:
onEvent
        {
                set "Fire_Mode::text" "gui::mode"
        }

        windowDef Fire_Mode
   {
      text   "gui::mode"
      rect   366,403,121,71
      forecolor   1,1,0,0.99215692
      visible   1
      textscale   0.30000001
      textalign   1
      backcolor   0.50196081,0,0,1
   }


Knowing my luck..the solution is simple, and right in front of my nose..... But, at the moment, it does not work :(

Any help would be greatly appreciated.....

Thanks in advance.

P.S. The back color will not be in the final release....just was there for testing....



S@TaNiC@Posted: Fri Jun 03, 2005 10:20 am :
Hi, Well if your calling setGuiParm( "mode", "semi" ); like that then its trying to apply a variable called mode onto a gui held on the pistol.

I think you need to do step 3 from goliathvt's tut and explicitly define the hud on the info_player_start entity.

Key: gui
Value: guis/hud.gui

Then in your pistol script reference it like .
Code:
$info_player_start.setGuiParm( "mode", "semi" );


Hope that helps.



Cody64@Posted: Fri Jun 03, 2005 5:49 pm :
Unless I'm misunderstanding, I think that technique only works Map scripts..... Maybe I'm wrong though....I'm still sort of a noob to guis :(



S@TaNiC@Posted: Sat Jun 04, 2005 5:18 am :
Bare with me cody64 this does end in a solution but theres most probably a few eggs to suck first.

There is no reason why this should not work no matter what type of script it is in.
There are only 2 types of script (something that when i get a little time i would like to change in the wiki)

1 OBJECT script - AI or WEAPON scripts for instance are both object scripts they run once for each entity they are referenced by. This is set in the entities def file using the key "scriptobject".
e.g each monster you spawn is runnig its own version of its script even if they are the same type of monster. The script is running for a specific entity so there is no need to reference this entity for commands hence the reason you can say pos = getOrigin(); in a monster script and it will return the position of this monster. The other thing special about object scripts is that they can inherit variables and functions from another script, like all monsters inherit stuff from monster_base.script.

2 MAP script - Just a plain old script has no special features other than it runs for the named map only. In a map script you have to reference every entity before a command.
e.g pos = $mymonster.getOrigin();


setGuiParm( "parm name", value);- This sets a variable on the referenced entity's gui (which is found from the entitys "gui" key) to the value specified.

OBJECT - for example the BFG has in its script setGuiParm( "powerlevel", 0 ); this sets a variable on the BFG's gui, its gui is defined in the BFG's def file "gui" "guis/weapons/bfg.gui".

MAP - if you were to place a func_static in your map named mystatic with a k/v of "gui" "gui/mygui.gui" you would then reference it in the map script as $mystatic.setGuiParm("parm name", value);


So, you wish to set a value on an entitys gui (in this case the player for the hud) from an object script that is not the entitys scriptobject (in this case weapon_pistol). So you would need to write $player1.setGuiParm("parm name", value). Although writing $player1 would only make it work if you were player1 (several things could screw this up especially multiplayer).
Because the setGuiParm command looks at the "gui" key on the referenced entity to know which gui to apply this variable to we also need to specify the gui on the player entity.
_________________________________
OK thats the egg sucking over with, now on to the solution. I have tested this and it seems to work ok for both SP and MP (as i have not played your mod :oops:, so wasnt sure what you needed).

Open up player.def and add a k/v of "gui" "guis/hud.gui" to the entitydef player_doommarine. This is our SP players reference to its gui ( the hud).
Open up mp.def and add a k/v of "gui" "guis/mphud.gui" to the entitydef player_doommarine_mp. This is our MP players reference to its gui.

Then for your weapon script add to the objects variable list
Code:
entity player;

then in the init function
Code:
player = getOwner();
This gets around the problem of you may not be player1.

Then where ever you need it, set your gui variable like so
Code:
player.setGuiParm("parm name", value);

Other than creating your windowDef in the hud and mphud thats it. You shouldnt need the onevent either from what i tested.

Well hope that all makes sense made a little bit of a pigs ear out of the post. :)



Cody64@Posted: Sat Jun 04, 2005 7:23 pm :
IT WORKS NOW :O Thank you S@TaNiC :D This makes the using fire modes in the mod much more convenient now :) For example, when I have the Shotgun equipped, I can press 'E' to swith between single shot (regular), double blast, and full auto. Now, I can have the selected fire mode shown on the hud :D

Quote:
(as i have not played your mod , so wasnt sure what you needed).


Well, we have released our first Demo, which you can try if you'd like. Here is a link to one of the sites you can download it from:

http://doom3.filefront.com/file/DOOM_Chronicles_Chapter_One_beta_demo;38182x#619013

Once again, thanks for the help :)