- [li]Content
[/li]This tutorial describes the setting of options with commandline variables (cvars) via menus.
[li]Introduction
[/li]Because I don’t like hardcoded “options” very much I tried to figure out the alternative way:
Setting options with variables via menu.
As example I choose the changing of the players speed in dependence on his health.
[li]Resources
[/li]The resources I have found are all for Q3. But to get an idea of the order of events they are pretty good.
[list=a:cd224e746b]
[li]Menu-file description
[/li]Quake III: Team Arena Menu Files
[li]Usage of cvars
[/li]ARTICLE 9 - Cvars, commands, and VM Communication
[li]Headerfiles
[/li]
[quote=“RR2DO2”]
Little tip, read through the menumacros.h file, it has some fancy stuff in it.
[/quote]
Also take a look at “menudef.h”.
[li]Menus
[/li]Create the new directory “ui” in the mod-directory.
Copy the files “hostgame.menu” and “menus.txt” out of the “…\WET_Source\etmain\ui”- into the new created “…\ET\mod\ui” directory.
- [li]Create a new menu file in the “…\ET\mod\ui” directory
[/li]Create a new menu file named “hostgame_additional.menu”. This file will contain all the dialog elements that are needed to set the desired options.
Tip: I have taken the original file “hostgame_advanced.menu”, have copied it to “…\ET\mod\ui”, have renamed it to “hostgame_additional.menu” and have edited it to suit my needs.
Tip: Take a look at “menumacros.h” and “menudef.h” for predefined dialog elements.
Because I have only one option I only add one dialog element - a numeric field.
The following code-block contains the whole new menu:
#include "ui/menudef.h" //***** DEFINES ***** #define WINDOW_X 16 #define WINDOW_Y 16 #define WINDOW_WIDTH 608 #define WINDOW_HEIGHT 448 #define GROUP_NAME "grpHostGameAdditional" //***** MACROS ***** #include "ui/menumacros.h" //***** HOSTGAME ADDITIONAL MENU ***** menuDef { name "hostgame_additional" visible 0 fullscreen 0 rect WINDOW_X WINDOW_Y WINDOW_WIDTH WINDOW_HEIGHT style WINDOW_STYLE_FILLED onESC { close hostgame_additional ; open hostgame } //***** WINDOW ***** WINDOW( "HOST GAME: Additional Options", 266 ) // DONT KNOW WHAT 266 MEANS //***** SUBWINDOWS ***** #define SUBWINDOW_WIDTH WINDOW_WIDTH-12 //***** ADDITIONAL OPTIONS *****// SUBWINDOW( 6, 32, (SUBWINDOW_WIDTH), 29, "ADDITIONAL OPTIONS" ) //FOR EXPLANTION PLEASE SEE "menumacros.h" NUMERICFIELD( 8, 48, (SUBWINDOW_WIDTH-4), 10, "Speed at 1 HP (in percentage):", .2, 8, "mod_speedpercentage", 3, "The percentage of speed from normal speed that a player will move with at 1HP." ) //***** Buttons ***** BUTTON( 6, WINDOW_HEIGHT-24, .5*(WINDOW_WIDTH-18), 18, "BACK", .3, 14, close hostgame_additional ; open hostgame ) BUTTON( 6+.5*(WINDOW_WIDTH-18)+6, WINDOW_HEIGHT-24, .5*(WINDOW_WIDTH-18), 18, "DEFAULT", .3, 14, open hostgame_additional_default ) }
[li]Create a new default-settings-dialog file in the “…\ET\mod\ui” directory
[/li]Create a new menu file named “hostgame_additional_default.menu”.
This dialog-menu will be used to set the default settings.
Tip: I have taken the original file “hostgame_advanced_default.menu”, have copied it to …\ET\mod\ui, have renamed it to “hostgame_additional_default.menu” and have edited it to suit my needs.
The following code-block contains the whole new menu:
#include "ui/menudef.h" // Defines // #define WINDOW_X 0 #define WINDOW_Y 0 #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 #define GROUP_NAME "grpHostgameAdditionalDefault" // Macros // #include "ui/menumacros.h" // Host Game Additional Default Menu // #define DEFAULT_ADDITIONAL_SETTINGS setcvar mod_speedpercentage 100 ; \ menuDef { name "hostgame_additional_default" visible 0 fullscreen 0 rect WINDOW_X WINDOW_Y WINDOW_WIDTH WINDOW_HEIGHT style WINDOW_STYLE_FILLED popup fadeClamp 0.5 onOpen { setitemcolor background backcolor 0 0 0 0 ; fadein background } onESC { close hostgame_additional_default ; open hostgame_additional } // Background // itemDef { name "background" rect 0 0 640 480 style WINDOW_STYLE_FILLED background "ui/assets/fadebox.tga" backcolor 0 0 0 0 visible 1 decoration } // Subwindows // #define SUBWINDOW_WIDTH 192 #define SUBWINDOW_HEIGHT 88 #define SUBWINDOW_X .5 * (WINDOW_WIDTH - SUBWINDOW_WIDTH) #define SUBWINDOW_Y .5 * (WINDOW_HEIGHT - SUBWINDOW_HEIGHT) SUBWINDOWBLACK( SUBWINDOW_X, SUBWINDOW_Y, SUBWINDOW_WIDTH, SUBWINDOW_HEIGHT, "DEFAULT ADDITIONAL SETTINGS" ) LABEL( SUBWINDOW_X+2, SUBWINDOW_Y+16, (SUBWINDOW_WIDTH)-8, 10, "Reset additional settings to default?", .2, ITEM_ALIGN_CENTER, .5*((SUBWINDOW_WIDTH)-4), 8 ) BUTTON( SUBWINDOW_X+6, SUBWINDOW_Y+SUBWINDOW_HEIGHT-24, .5*(SUBWINDOW_WIDTH-18), 18, "YES", .3, 14, close hostgame_additional_default ; open hostgame_additional ; DEFAULT_ADDITIONAL_SETTINGS ) BUTTON( SUBWINDOW_X+6+.5*(SUBWINDOW_WIDTH-18)+6, SUBWINDOW_Y+SUBWINDOW_HEIGHT-24, .5*(SUBWINDOW_WIDTH-18), 18, "NO", .3, 14, close hostgame_additional_default ; open hostgame_additional ) }
[li]Editing “…\ET\mod\ui\hostgame.menu”
[/li]To make the new menu accessible one of the original menus has to be edited.
Because there’s already the hostgame advanced menu (accessible by the hostgame menu) I decided to make the new menu also accessible by the hostgame menu.
All that is to be done is to resize the old buttons to receive some space for a new button and to insert a new button.
Due to the workflow I decided to add the new button as third button.
Replace the group of Buttons at the end of the file by the following lines:
// Buttons // BUTTON( 6, WINDOW_HEIGHT-24, .25*(WINDOW_WIDTH-24), 18, "BACK", .3, 14, close hostgame ; open main ) BUTTON( 6+.25*(WINDOW_WIDTH-24)+4, WINDOW_HEIGHT-24, .25*(WINDOW_WIDTH-24), 18, "ADVANCED", .3, 14, close hostgame ; open hostgame_advanced ) BUTTON( 6+.25*(WINDOW_WIDTH-24)+4+.25*(WINDOW_WIDTH-24)+4, WINDOW_HEIGHT-24, .25*(WINDOW_WIDTH-24), 18, "ADDITIONAL", .3, 14, close hostgame ; open hostgame_additional ) BUTTON( 6+.25*(WINDOW_WIDTH-24)+4+.25*(WINDOW_WIDTH-24)+4+.25*(WINDOW_WIDTH-25)+4, WINDOW_HEIGHT-24, .25*(WINDOW_WIDTH-24), 18, "START SERVER", .3, 14, conditionalScript ui_dedicated 0 ( "open hostgame_dedicated_warning" ) ( "uiScript StartServer" ) )
Now the order of appearence is as follows:
BACK | ADVANCED | ADDITIONAL | START SERVER
[li]Editing “…\ET\mod\ui\menus.txt”
[/li]The file “menus.txt” has to be edited to get the new menus into the game.
Insert the following two lines into this file somewhere between the oppening “{”- and closing “}”-bracket:
loadMenu { "ui/hostgame_additional.menu" } loadMenu { "ui/hostgame_additional_default.menu" }
As they are similar to the hostgame menus I decided to insert these lines below the lines containing the other hostgame menus.
[li]Source-code
[/li]To use the option the source code has to be edited as well.
Several changes have to be done.
Although I know that the option that I use is a game option I decided to insert the cvar in the ui-part of the game because I use this option in an both-game (bg_) file.
Note that the name “mod_speedperentage” represents the variable that is also used in the numeric field in the “hostgame_additional.menu” file.
- [li]ui_main.c
[/li]Insert the following code into the file “ui_main.c” starting at line 8090:
//ui_main.c //+***** MYMOD ***** vmCvar_t mod_speedpercentage; //-***** MYMOD *****
Insert the following code into the file “ui_main.c” starting around line 8238 (below line: “cvarTable_t cvarTable[] = {”):
//ui_main.c cvarTable_t //+***** MYMOD ***** { &mod_speedpercentage, "mod_speedpercentage", "100", CVAR_ARCHIVE }, //-***** MYMOD *****
[li]ui_local.h
[/li]Insert the following code into the file “ui.local.h” starting at line 11:
//ui_local.h //+***** MYMOD ***** extern vmCvar_t mod_speedpercentage; //-***** MYMOD *****
[li]Usage of the cvar
[/li]To get the value of the used cvar the function “trap_Cvar_VariableStringBuffer” is used.
To set the value of the used cvar the function “trap_Cvar_Set” is used.
Insert the following code (declaration of the used variables) into file “bg_pmove.c” starting line 25:
//+***** MYMOD ***** float percentage; char modbuffer[4]; extern void trap_Cvar_VariableStringBuffer ( const char * var_name , char * buffer , int bufsize ) ; extern void trap_Cvar_Set ( const char * var_name , const char * value ) ; //-***** MYMOD *****
Note: I had to declare the two functions also to avoid warning messages of the compiler.
Now the part where the value of the cvar is used is reached.
Insert the code between the “MYMOD’s” into the file “bg_pmove.c” around line 547:
if (gametype == GT_SINGLE_PLAYER || gametype == GT_COOP) { // Adjust the movespeed scale *= (((float) movespeed)/(float) 127); } // if (gametype == GT_SINGLE_PLAYER)... //+ ***** MYMOD ***** //CHANGED: FUNCTION: SCALE = SCALE * [(1-A) * HEALTH/MAX_HEALTH + A] //WITH A AS FACTOR AT 0 HEALTH e.g. FOR 3/4 OF ORIGINAL SPEED AT 0 HEALTH A HAS TO BE REPLACED BY 0.75 trap_Cvar_VariableStringBuffer("mod_speedpercentage", modbuffer, sizeof(modbuffer)); percentage = atof(modbuffer); if (percentage < 0.0 || percentage > 150.0 ) { percentage = 100.0; //DEFAULT NO CHANGE AT ALL trap_Cvar_Set( "mod_speedpercentage", "100"); } scale = scale * ( percentage / 100.0 + (1.0 - percentage / 100.0) * pm->ps->stats[ STAT_HEALTH ] / pm->ps->stats[ STAT_MAX_HEALTH ] ); //- ***** MYMOD ***** return scale; }
After editing the source files and recompiling the dll’s you can set your options after starting your mod by:
Main -> Hostgame -> Hostgame Additional -> Setting the Options -> Back -> Start Server
Note: Although it seems not to be correct in details it works fine.
[li]To do:
[/li][list=a]
[li]Error-trapping
[/li][li]Commandline-setting of cvar
[/li][li]Setting defaults for a subwindow
[/li][li]Credits
[/li][li]German translation
[/li][/list]
[li]Credits
[/li][list=a]
[/list]
[li]Open questions
[/li][list=a]
[/list]
[li]Final
[/li]Due to the reason that I am a total nOOb in coding but trying to get into it please report mistakes.
Also please feel free to make suggestions, to give comments and to tell ideas.
But most important please correct my English.
Although I try my best I think it’s not as good as it should be.
[/list:o:cd224e746b]
