Annotation of quake2/client/menu.c, revision 1.1.1.3

1.1       root        1: #include <ctype.h>
1.1.1.2   root        2: #ifdef _WIN32
1.1       root        3: #include <io.h>
1.1.1.2   root        4: #endif
1.1       root        5: #include "client.h"
                      6: #include "../client/qmenu.h"
1.1.1.2   root        7: 
1.1       root        8: static int     m_main_cursor;
1.1.1.2   root        9: 
1.1       root       10: #define NUM_CURSOR_FRAMES 15
1.1.1.2   root       11: 
1.1       root       12: static char *menu_in_sound             = "misc/menu1.wav";
                     13: static char *menu_move_sound   = "misc/menu2.wav";
                     14: static char *menu_out_sound            = "misc/menu3.wav";
1.1.1.2   root       15: 
1.1       root       16: void M_Menu_Main_f (void);
                     17:        void M_Menu_Game_f (void);
                     18:                void M_Menu_LoadGame_f (void);
                     19:                void M_Menu_SaveGame_f (void);
                     20:                void M_Menu_PlayerConfig_f (void);
1.1.1.2   root       21:                        void M_Menu_DownloadOptions_f (void);
1.1       root       22:                void M_Menu_Credits_f( void );
                     23:        void M_Menu_Multiplayer_f( void );
                     24:                void M_Menu_JoinServer_f (void);
                     25:                        void M_Menu_AddressBook_f( void );
                     26:                void M_Menu_StartServer_f (void);
                     27:                        void M_Menu_DMOptions_f (void);
                     28:        void M_Menu_Video_f (void);
                     29:        void M_Menu_Options_f (void);
                     30:                void M_Menu_Keys_f (void);
                     31:        void M_Menu_Quit_f (void);
                     32: 
                     33:        void M_Menu_Credits( void );
1.1.1.2   root       34: 
1.1       root       35: qboolean       m_entersound;           // play after drawing a frame, so caching
                     36:                                                                // won't disrupt the sound
1.1.1.2   root       37: 
1.1       root       38: void   (*m_drawfunc) (void);
                     39: const char *(*m_keyfunc) (int key);
1.1.1.2   root       40: 
1.1       root       41: //=============================================================================
                     42: /* Support Routines */
1.1.1.2   root       43: 
1.1       root       44: #define        MAX_MENU_DEPTH  8
1.1.1.2   root       45: 
                     46: 
1.1       root       47: typedef struct
                     48: {
                     49:        void    (*draw) (void);
                     50:        const char *(*key) (int k);
                     51: } menulayer_t;
1.1.1.2   root       52: 
1.1       root       53: menulayer_t    m_layers[MAX_MENU_DEPTH];
                     54: int            m_menudepth;
                     55: 
                     56: static void M_Banner( char *name )
                     57: {
                     58:        int w, h;
                     59: 
                     60:        re.DrawGetPicSize (&w, &h, name );
                     61:        re.DrawPic( viddef.width / 2 - w / 2, viddef.height / 2 - 110, name );
                     62: }
1.1.1.2   root       63: 
1.1       root       64: void M_PushMenu ( void (*draw) (void), const char *(*key) (int k) )
                     65: {
                     66:        int             i;
                     67: 
                     68:        if (Cvar_VariableValue ("maxclients") == 1 
                     69:                && Com_ServerState ())
                     70:                Cvar_Set ("paused", "1");
1.1.1.2   root       71: 
1.1.1.3 ! root       72:        // if this menu is already present, drop back to that level
1.1       root       73:        // to avoid stacking menus by hotkeys
                     74:        for (i=0 ; i<m_menudepth ; i++)
                     75:                if (m_layers[i].draw == draw &&
                     76:                        m_layers[i].key == key)
                     77:                {
                     78:                        m_menudepth = i;
                     79:                }
1.1.1.2   root       80: 
1.1       root       81:        if (i == m_menudepth)
                     82:        {
                     83:                if (m_menudepth >= MAX_MENU_DEPTH)
                     84:                        Com_Error (ERR_FATAL, "M_PushMenu: MAX_MENU_DEPTH");
                     85:                m_layers[m_menudepth].draw = m_drawfunc;
                     86:                m_layers[m_menudepth].key = m_keyfunc;
                     87:                m_menudepth++;
                     88:        }
1.1.1.2   root       89: 
1.1       root       90:        m_drawfunc = draw;
                     91:        m_keyfunc = key;
1.1.1.2   root       92: 
1.1       root       93:        m_entersound = true;
1.1.1.2   root       94: 
1.1       root       95:        cls.key_dest = key_menu;
                     96: }
1.1.1.2   root       97: 
1.1       root       98: void M_ForceMenuOff (void)
                     99: {
                    100:        m_drawfunc = 0;
                    101:        m_keyfunc = 0;
                    102:        cls.key_dest = key_game;
                    103:        m_menudepth = 0;
                    104:        Key_ClearStates ();
                    105:        Cvar_Set ("paused", "0");
                    106: }
1.1.1.2   root      107: 
1.1       root      108: void M_PopMenu (void)
                    109: {
                    110:        S_StartLocalSound( menu_out_sound );
                    111:        if (m_menudepth < 1)
                    112:                Com_Error (ERR_FATAL, "M_PopMenu: depth < 1");
                    113:        m_menudepth--;
1.1.1.2   root      114: 
1.1       root      115:        m_drawfunc = m_layers[m_menudepth].draw;
                    116:        m_keyfunc = m_layers[m_menudepth].key;
1.1.1.2   root      117: 
1.1       root      118:        if (!m_menudepth)
                    119:                M_ForceMenuOff ();
                    120: }
1.1.1.2   root      121: 
                    122: 
1.1       root      123: const char *Default_MenuKey( menuframework_s *m, int key )
                    124: {
                    125:        const char *sound = NULL;
                    126:        menucommon_s *item;
1.1.1.2   root      127: 
1.1       root      128:        if ( m )
                    129:        {
                    130:                if ( ( item = Menu_ItemAtCursor( m ) ) != 0 )
                    131:                {
                    132:                        if ( item->type == MTYPE_FIELD )
                    133:                        {
                    134:                                if ( Field_Key( ( menufield_s * ) item, key ) )
                    135:                                        return NULL;
                    136:                        }
                    137:                }
                    138:        }
1.1.1.2   root      139: 
1.1       root      140:        switch ( key )
                    141:        {
                    142:        case K_ESCAPE:
                    143:                M_PopMenu();
                    144:                return menu_out_sound;
                    145:        case K_KP_UPARROW:
                    146:        case K_UPARROW:
                    147:                if ( m )
                    148:                {
                    149:                        m->cursor--;
                    150:                        Menu_AdjustCursor( m, -1 );
                    151:                        sound = menu_move_sound;
                    152:                }
                    153:                break;
                    154:        case K_TAB:
                    155:                if ( m )
                    156:                {
                    157:                        m->cursor++;
                    158:                        Menu_AdjustCursor( m, 1 );
                    159:                        sound = menu_move_sound;
                    160:                }
                    161:                break;
                    162:        case K_KP_DOWNARROW:
                    163:        case K_DOWNARROW:
                    164:                if ( m )
                    165:                {
                    166:                        m->cursor++;
                    167:                        Menu_AdjustCursor( m, 1 );
                    168:                        sound = menu_move_sound;
                    169:                }
                    170:                break;
                    171:        case K_KP_LEFTARROW:
                    172:        case K_LEFTARROW:
                    173:                if ( m )
                    174:                {
                    175:                        Menu_SlideItem( m, -1 );
                    176:                        sound = menu_move_sound;
                    177:                }
                    178:                break;
                    179:        case K_KP_RIGHTARROW:
                    180:        case K_RIGHTARROW:
                    181:                if ( m )
                    182:                {
                    183:                        Menu_SlideItem( m, 1 );
                    184:                        sound = menu_move_sound;
                    185:                }
                    186:                break;
                    187: 
                    188:        case K_MOUSE1:
                    189:        case K_MOUSE2:
                    190:        case K_MOUSE3:
                    191:        case K_JOY1:
                    192:        case K_JOY2:
                    193:        case K_JOY3:
                    194:        case K_JOY4:
                    195:        case K_AUX1:
                    196:        case K_AUX2:
                    197:        case K_AUX3:
                    198:        case K_AUX4:
                    199:        case K_AUX5:
                    200:        case K_AUX6:
                    201:        case K_AUX7:
                    202:        case K_AUX8:
                    203:        case K_AUX9:
                    204:        case K_AUX10:
                    205:        case K_AUX11:
                    206:        case K_AUX12:
                    207:        case K_AUX13:
                    208:        case K_AUX14:
                    209:        case K_AUX15:
                    210:        case K_AUX16:
                    211:        case K_AUX17:
                    212:        case K_AUX18:
                    213:        case K_AUX19:
                    214:        case K_AUX20:
                    215:        case K_AUX21:
                    216:        case K_AUX22:
                    217:        case K_AUX23:
                    218:        case K_AUX24:
                    219:        case K_AUX25:
                    220:        case K_AUX26:
                    221:        case K_AUX27:
                    222:        case K_AUX28:
                    223:        case K_AUX29:
                    224:        case K_AUX30:
                    225:        case K_AUX31:
                    226:        case K_AUX32:
                    227:                
                    228:        case K_KP_ENTER:
                    229:        case K_ENTER:
                    230:                if ( m )
                    231:                        Menu_SelectItem( m );
                    232:                sound = menu_move_sound;
                    233:                break;
                    234:        }
1.1.1.2   root      235: 
1.1       root      236:        return sound;
                    237: }
1.1.1.2   root      238: 
1.1       root      239: //=============================================================================
1.1.1.2   root      240: 
1.1       root      241: /*
                    242: ================
                    243: M_DrawCharacter
1.1.1.2   root      244: 
1.1       root      245: Draws one solid graphics character
                    246: cx and cy are in 320*240 coordinates, and will be centered on
                    247: higher res screens.
                    248: ================
                    249: */
                    250: void M_DrawCharacter (int cx, int cy, int num)
                    251: {
                    252:        re.DrawChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1), num);
                    253: }
1.1.1.2   root      254: 
1.1       root      255: void M_Print (int cx, int cy, char *str)
                    256: {
                    257:        while (*str)
                    258:        {
                    259:                M_DrawCharacter (cx, cy, (*str)+128);
                    260:                str++;
                    261:                cx += 8;
                    262:        }
                    263: }
1.1.1.2   root      264: 
1.1       root      265: void M_PrintWhite (int cx, int cy, char *str)
                    266: {
                    267:        while (*str)
                    268:        {
                    269:                M_DrawCharacter (cx, cy, *str);
                    270:                str++;
                    271:                cx += 8;
                    272:        }
                    273: }
1.1.1.2   root      274: 
1.1       root      275: void M_DrawPic (int x, int y, char *pic)
                    276: {
                    277:        re.DrawPic (x + ((viddef.width - 320)>>1), y + ((viddef.height - 240)>>1), pic);
                    278: }
1.1.1.2   root      279: 
                    280: 
1.1       root      281: /*
                    282: =============
                    283: M_DrawCursor
1.1.1.2   root      284: 
1.1       root      285: Draws an animating cursor with the point at
                    286: x,y.  The pic will extend to the left of x,
                    287: and both above and below y.
                    288: =============
                    289: */
                    290: void M_DrawCursor( int x, int y, int f )
                    291: {
                    292:        char    cursorname[80];
                    293:        static qboolean cached;
                    294: 
                    295:        if ( !cached )
                    296:        {
                    297:                int i;
                    298: 
                    299:                for ( i = 0; i < NUM_CURSOR_FRAMES; i++ )
                    300:                {
                    301:                        Com_sprintf( cursorname, sizeof( cursorname ), "m_cursor%d", i );
                    302: 
                    303:                        re.RegisterPic( cursorname );
                    304:                }
                    305:                cached = true;
                    306:        }
1.1.1.2   root      307: 
1.1       root      308:        Com_sprintf( cursorname, sizeof(cursorname), "m_cursor%d", f );
                    309:        re.DrawPic( x, y, cursorname );
                    310: }
1.1.1.2   root      311: 
1.1       root      312: void M_DrawTextBox (int x, int y, int width, int lines)
                    313: {
                    314:        int             cx, cy;
                    315:        int             n;
1.1.1.2   root      316: 
1.1       root      317:        // draw left side
                    318:        cx = x;
                    319:        cy = y;
                    320:        M_DrawCharacter (cx, cy, 1);
                    321:        for (n = 0; n < lines; n++)
                    322:        {
                    323:                cy += 8;
                    324:                M_DrawCharacter (cx, cy, 4);
                    325:        }
                    326:        M_DrawCharacter (cx, cy+8, 7);
1.1.1.2   root      327: 
1.1       root      328:        // draw middle
                    329:        cx += 8;
                    330:        while (width > 0)
                    331:        {
                    332:                cy = y;
                    333:                M_DrawCharacter (cx, cy, 2);
                    334:                for (n = 0; n < lines; n++)
                    335:                {
                    336:                        cy += 8;
                    337:                        M_DrawCharacter (cx, cy, 5);
                    338:                }
                    339:                M_DrawCharacter (cx, cy+8, 8);
                    340:                width -= 1;
                    341:                cx += 8;
                    342:        }
1.1.1.2   root      343: 
1.1       root      344:        // draw right side
                    345:        cy = y;
                    346:        M_DrawCharacter (cx, cy, 3);
                    347:        for (n = 0; n < lines; n++)
                    348:        {
                    349:                cy += 8;
                    350:                M_DrawCharacter (cx, cy, 6);
                    351:        }
                    352:        M_DrawCharacter (cx, cy+8, 9);
                    353: }
1.1.1.2   root      354: 
1.1       root      355:                
                    356: /*
                    357: =======================================================================
1.1.1.2   root      358: 
1.1       root      359: MAIN MENU
1.1.1.2   root      360: 
1.1       root      361: =======================================================================
                    362: */
                    363: #define        MAIN_ITEMS      5
1.1.1.2   root      364: 
                    365: 
1.1       root      366: void M_Main_Draw (void)
                    367: {
                    368:        int i;
                    369:        int w, h;
                    370:        int ystart;
                    371:        int     xoffset;
                    372:        int widest = -1;
                    373:        int totalheight = 0;
                    374:        char litname[80];
                    375:        char *names[] =
                    376:        {
                    377:                "m_main_game",
                    378:                "m_main_multiplayer",
                    379:                "m_main_options",
                    380:                "m_main_video",
                    381:                "m_main_quit",
                    382:                0
                    383:        };
1.1.1.2   root      384: 
1.1       root      385:        for ( i = 0; names[i] != 0; i++ )
                    386:        {
                    387:                re.DrawGetPicSize( &w, &h, names[i] );
1.1.1.2   root      388: 
1.1       root      389:                if ( w > widest )
                    390:                        widest = w;
                    391:                totalheight += ( h + 12 );
                    392:        }
                    393: 
                    394:        ystart = ( viddef.height / 2 - 110 );
                    395:        xoffset = ( viddef.width - widest + 70 ) / 2;
1.1.1.2   root      396: 
1.1       root      397:        for ( i = 0; names[i] != 0; i++ )
                    398:        {
                    399:                if ( i != m_main_cursor )
                    400:                        re.DrawPic( xoffset, ystart + i * 40 + 13, names[i] );
                    401:        }
                    402:        strcpy( litname, names[m_main_cursor] );
                    403:        strcat( litname, "_sel" );
                    404:        re.DrawPic( xoffset, ystart + m_main_cursor * 40 + 13, litname );
1.1.1.2   root      405: 
1.1       root      406:        M_DrawCursor( xoffset - 25, ystart + m_main_cursor * 40 + 11, (int)(cls.realtime / 100)%NUM_CURSOR_FRAMES );
1.1.1.2   root      407: 
1.1       root      408:        re.DrawGetPicSize( &w, &h, "m_main_plaque" );
                    409:        re.DrawPic( xoffset - 30 - w, ystart, "m_main_plaque" );
1.1.1.2   root      410: 
1.1       root      411:        re.DrawPic( xoffset - 30 - w, ystart + h + 5, "m_main_logo" );
                    412: }
1.1.1.2   root      413: 
                    414: 
1.1       root      415: const char *M_Main_Key (int key)
                    416: {
                    417:        const char *sound = menu_move_sound;
1.1.1.2   root      418: 
1.1       root      419:        switch (key)
                    420:        {
                    421:        case K_ESCAPE:
                    422:                M_PopMenu ();
                    423:                break;
                    424: 
                    425:        case K_KP_DOWNARROW:
                    426:        case K_DOWNARROW:
                    427:                if (++m_main_cursor >= MAIN_ITEMS)
                    428:                        m_main_cursor = 0;
                    429:                return sound;
1.1.1.2   root      430: 
1.1       root      431:        case K_KP_UPARROW:
                    432:        case K_UPARROW:
                    433:                if (--m_main_cursor < 0)
                    434:                        m_main_cursor = MAIN_ITEMS - 1;
                    435:                return sound;
                    436: 
                    437:        case K_KP_ENTER:
                    438:        case K_ENTER:
                    439:                m_entersound = true;
1.1.1.2   root      440: 
1.1       root      441:                switch (m_main_cursor)
                    442:                {
                    443:                case 0:
                    444:                        M_Menu_Game_f ();
                    445:                        break;
1.1.1.2   root      446: 
1.1       root      447:                case 1:
                    448:                        M_Menu_Multiplayer_f();
                    449:                        break;
1.1.1.2   root      450: 
1.1       root      451:                case 2:
                    452:                        M_Menu_Options_f ();
                    453:                        break;
1.1.1.2   root      454: 
1.1       root      455:                case 3:
                    456:                        M_Menu_Video_f ();
                    457:                        break;
1.1.1.2   root      458: 
1.1       root      459:                case 4:
                    460:                        M_Menu_Quit_f ();
                    461:                        break;
                    462:                }
                    463:        }
1.1.1.2   root      464: 
1.1       root      465:        return NULL;
                    466: }
1.1.1.2   root      467: 
                    468: 
1.1       root      469: void M_Menu_Main_f (void)
                    470: {
                    471:        M_PushMenu (M_Main_Draw, M_Main_Key);
                    472: }
                    473: 
                    474: /*
                    475: =======================================================================
                    476: 
                    477: MULTIPLAYER MENU
                    478: 
                    479: =======================================================================
                    480: */
                    481: static menuframework_s s_multiplayer_menu;
                    482: static menuaction_s            s_join_network_server_action;
                    483: static menuaction_s            s_start_network_server_action;
                    484: static menuaction_s            s_player_setup_action;
                    485: 
                    486: static void Multiplayer_MenuDraw (void)
                    487: {
                    488:        M_Banner( "m_banner_multiplayer" );
                    489: 
                    490:        Menu_AdjustCursor( &s_multiplayer_menu, 1 );
                    491:        Menu_Draw( &s_multiplayer_menu );
                    492: }
                    493: 
                    494: static void PlayerSetupFunc( void *unused )
                    495: {
                    496:        M_Menu_PlayerConfig_f();
                    497: }
                    498: 
                    499: static void JoinNetworkServerFunc( void *unused )
                    500: {
                    501:        M_Menu_JoinServer_f();
                    502: }
                    503: 
                    504: static void StartNetworkServerFunc( void *unused )
                    505: {
                    506:        M_Menu_StartServer_f ();
                    507: }
                    508: 
                    509: void Multiplayer_MenuInit( void )
                    510: {
                    511:        s_multiplayer_menu.x = viddef.width * 0.50 - 64;
                    512:        s_multiplayer_menu.nitems = 0;
                    513: 
                    514:        s_join_network_server_action.generic.type       = MTYPE_ACTION;
                    515:        s_join_network_server_action.generic.flags  = QMF_LEFT_JUSTIFY;
                    516:        s_join_network_server_action.generic.x          = 0;
                    517:        s_join_network_server_action.generic.y          = 0;
                    518:        s_join_network_server_action.generic.name       = " join network server";
                    519:        s_join_network_server_action.generic.callback = JoinNetworkServerFunc;
                    520: 
                    521:        s_start_network_server_action.generic.type      = MTYPE_ACTION;
                    522:        s_start_network_server_action.generic.flags  = QMF_LEFT_JUSTIFY;
                    523:        s_start_network_server_action.generic.x         = 0;
                    524:        s_start_network_server_action.generic.y         = 10;
                    525:        s_start_network_server_action.generic.name      = " start network server";
                    526:        s_start_network_server_action.generic.callback = StartNetworkServerFunc;
                    527: 
                    528:        s_player_setup_action.generic.type      = MTYPE_ACTION;
                    529:        s_player_setup_action.generic.flags  = QMF_LEFT_JUSTIFY;
                    530:        s_player_setup_action.generic.x         = 0;
                    531:        s_player_setup_action.generic.y         = 20;
                    532:        s_player_setup_action.generic.name      = " player setup";
                    533:        s_player_setup_action.generic.callback = PlayerSetupFunc;
                    534: 
                    535:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_join_network_server_action );
                    536:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_start_network_server_action );
                    537:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_player_setup_action );
                    538: 
1.1.1.2   root      539:        Menu_SetStatusBar( &s_multiplayer_menu, NULL );
                    540: 
1.1       root      541:        Menu_Center( &s_multiplayer_menu );
                    542: }
                    543: 
                    544: const char *Multiplayer_MenuKey( int key )
                    545: {
                    546:        return Default_MenuKey( &s_multiplayer_menu, key );
                    547: }
                    548: 
                    549: void M_Menu_Multiplayer_f( void )
                    550: {
                    551:        Multiplayer_MenuInit();
                    552:        M_PushMenu( Multiplayer_MenuDraw, Multiplayer_MenuKey );
                    553: }
1.1.1.2   root      554: 
1.1       root      555: /*
                    556: =======================================================================
                    557: 
                    558: KEYS MENU
                    559: 
                    560: =======================================================================
                    561: */
                    562: char *bindnames[][2] =
                    563: {
                    564: {"+attack",            "attack"},
                    565: {"weapnext",           "next weapon"},
                    566: {"+forward",           "walk forward"},
                    567: {"+back",                      "backpedal"},
                    568: {"+left",                      "turn left"},
                    569: {"+right",                     "turn right"},
                    570: {"+speed",                     "run"},
                    571: {"+moveleft",          "step left"},
                    572: {"+moveright",                 "step right"},
                    573: {"+strafe",            "sidestep"},
                    574: {"+lookup",            "look up"},
                    575: {"+lookdown",          "look down"},
                    576: {"centerview",                 "center view"},
                    577: {"+mlook",                     "mouse look"},
                    578: {"+klook",                     "keyboard look"},
                    579: {"+moveup",                    "up / jump"},
                    580: {"+movedown",          "down / crouch"},
1.1.1.2   root      581: 
1.1       root      582: {"inven",                      "inventory"},
                    583: {"invuse",                     "use item"},
                    584: {"invdrop",                    "drop item"},
                    585: {"invprev",                    "prev item"},
                    586: {"invnext",                    "next item"},
1.1.1.2   root      587: 
1.1       root      588: {"cmd help",           "help computer" }, 
                    589: { 0, 0 }
                    590: };
1.1.1.2   root      591: 
1.1       root      592: int                            keys_cursor;
                    593: static int             bind_grab;
1.1.1.2   root      594: 
1.1       root      595: static menuframework_s s_keys_menu;
                    596: static menuaction_s            s_keys_attack_action;
                    597: static menuaction_s            s_keys_change_weapon_action;
                    598: static menuaction_s            s_keys_walk_forward_action;
                    599: static menuaction_s            s_keys_backpedal_action;
                    600: static menuaction_s            s_keys_turn_left_action;
                    601: static menuaction_s            s_keys_turn_right_action;
                    602: static menuaction_s            s_keys_run_action;
                    603: static menuaction_s            s_keys_step_left_action;
                    604: static menuaction_s            s_keys_step_right_action;
                    605: static menuaction_s            s_keys_sidestep_action;
                    606: static menuaction_s            s_keys_look_up_action;
                    607: static menuaction_s            s_keys_look_down_action;
                    608: static menuaction_s            s_keys_center_view_action;
                    609: static menuaction_s            s_keys_mouse_look_action;
                    610: static menuaction_s            s_keys_keyboard_look_action;
                    611: static menuaction_s            s_keys_move_up_action;
                    612: static menuaction_s            s_keys_move_down_action;
                    613: static menuaction_s            s_keys_inventory_action;
                    614: static menuaction_s            s_keys_inv_use_action;
                    615: static menuaction_s            s_keys_inv_drop_action;
                    616: static menuaction_s            s_keys_inv_prev_action;
                    617: static menuaction_s            s_keys_inv_next_action;
1.1.1.2   root      618: 
1.1       root      619: static menuaction_s            s_keys_help_computer_action;
1.1.1.2   root      620: 
1.1       root      621: static void M_UnbindCommand (char *command)
                    622: {
                    623:        int             j;
                    624:        int             l;
                    625:        char    *b;
1.1.1.2   root      626: 
1.1       root      627:        l = strlen(command);
1.1.1.2   root      628: 
1.1       root      629:        for (j=0 ; j<256 ; j++)
                    630:        {
                    631:                b = keybindings[j];
                    632:                if (!b)
                    633:                        continue;
                    634:                if (!strncmp (b, command, l) )
                    635:                        Key_SetBinding (j, "");
                    636:        }
                    637: }
1.1.1.2   root      638: 
1.1       root      639: static void M_FindKeysForCommand (char *command, int *twokeys)
                    640: {
                    641:        int             count;
                    642:        int             j;
                    643:        int             l;
                    644:        char    *b;
1.1.1.2   root      645: 
1.1       root      646:        twokeys[0] = twokeys[1] = -1;
                    647:        l = strlen(command);
                    648:        count = 0;
1.1.1.2   root      649: 
1.1       root      650:        for (j=0 ; j<256 ; j++)
                    651:        {
                    652:                b = keybindings[j];
                    653:                if (!b)
                    654:                        continue;
                    655:                if (!strncmp (b, command, l) )
                    656:                {
                    657:                        twokeys[count] = j;
                    658:                        count++;
                    659:                        if (count == 2)
                    660:                                break;
                    661:                }
                    662:        }
                    663: }
1.1.1.2   root      664: 
1.1       root      665: static void KeyCursorDrawFunc( menuframework_s *menu )
                    666: {
                    667:        if ( bind_grab )
                    668:                re.DrawChar( menu->x, menu->y + menu->cursor * 9, '=' );
                    669:        else
                    670:                re.DrawChar( menu->x, menu->y + menu->cursor * 9, 12 + ( ( int ) ( Sys_Milliseconds() / 250 ) & 1 ) );
                    671: }
1.1.1.2   root      672: 
1.1       root      673: static void DrawKeyBindingFunc( void *self )
                    674: {
                    675:        int keys[2];
                    676:        menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2   root      677: 
1.1       root      678:        M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys);
                    679:                
                    680:        if (keys[0] == -1)
                    681:        {
                    682:                Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, "???" );
                    683:        }
                    684:        else
                    685:        {
                    686:                int x;
                    687:                const char *name;
1.1.1.2   root      688: 
1.1       root      689:                name = Key_KeynumToString (keys[0]);
1.1.1.2   root      690: 
1.1       root      691:                Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, name );
1.1.1.2   root      692: 
1.1       root      693:                x = strlen(name) * 8;
1.1.1.2   root      694: 
1.1       root      695:                if (keys[1] != -1)
                    696:                {
                    697:                        Menu_DrawString( a->generic.x + a->generic.parent->x + 24 + x, a->generic.y + a->generic.parent->y, "or" );
                    698:                        Menu_DrawString( a->generic.x + a->generic.parent->x + 48 + x, a->generic.y + a->generic.parent->y, Key_KeynumToString (keys[1]) );
                    699:                }
                    700:        }
                    701: }
1.1.1.2   root      702: 
1.1       root      703: static void KeyBindingFunc( void *self )
                    704: {
                    705:        menuaction_s *a = ( menuaction_s * ) self;
                    706:        int keys[2];
1.1.1.2   root      707: 
1.1       root      708:        M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys );
1.1.1.2   root      709: 
1.1       root      710:        if (keys[1] != -1)
                    711:                M_UnbindCommand( bindnames[a->generic.localdata[0]][0]);
1.1.1.2   root      712: 
1.1       root      713:        bind_grab = true;
1.1.1.2   root      714: 
1.1       root      715:        Menu_SetStatusBar( &s_keys_menu, "press a key or button for this action" );
                    716: }
1.1.1.2   root      717: 
1.1       root      718: static void Keys_MenuInit( void )
                    719: {
                    720:        int y = 0;
                    721:        int i = 0;
1.1.1.2   root      722: 
1.1       root      723:        s_keys_menu.x = viddef.width * 0.50;
                    724:        s_keys_menu.nitems = 0;
                    725:        s_keys_menu.cursordraw = KeyCursorDrawFunc;
1.1.1.2   root      726: 
1.1       root      727:        s_keys_attack_action.generic.type       = MTYPE_ACTION;
                    728:        s_keys_attack_action.generic.flags  = QMF_GRAYED;
                    729:        s_keys_attack_action.generic.x          = 0;
                    730:        s_keys_attack_action.generic.y          = y;
                    731:        s_keys_attack_action.generic.ownerdraw = DrawKeyBindingFunc;
                    732:        s_keys_attack_action.generic.localdata[0] = i;
                    733:        s_keys_attack_action.generic.name       = bindnames[s_keys_attack_action.generic.localdata[0]][1];
1.1.1.2   root      734: 
1.1       root      735:        s_keys_change_weapon_action.generic.type        = MTYPE_ACTION;
                    736:        s_keys_change_weapon_action.generic.flags  = QMF_GRAYED;
                    737:        s_keys_change_weapon_action.generic.x           = 0;
                    738:        s_keys_change_weapon_action.generic.y           = y += 9;
                    739:        s_keys_change_weapon_action.generic.ownerdraw = DrawKeyBindingFunc;
                    740:        s_keys_change_weapon_action.generic.localdata[0] = ++i;
                    741:        s_keys_change_weapon_action.generic.name        = bindnames[s_keys_change_weapon_action.generic.localdata[0]][1];
1.1.1.2   root      742: 
1.1       root      743:        s_keys_walk_forward_action.generic.type = MTYPE_ACTION;
                    744:        s_keys_walk_forward_action.generic.flags  = QMF_GRAYED;
                    745:        s_keys_walk_forward_action.generic.x            = 0;
                    746:        s_keys_walk_forward_action.generic.y            = y += 9;
                    747:        s_keys_walk_forward_action.generic.ownerdraw = DrawKeyBindingFunc;
                    748:        s_keys_walk_forward_action.generic.localdata[0] = ++i;
                    749:        s_keys_walk_forward_action.generic.name = bindnames[s_keys_walk_forward_action.generic.localdata[0]][1];
1.1.1.2   root      750: 
1.1       root      751:        s_keys_backpedal_action.generic.type    = MTYPE_ACTION;
                    752:        s_keys_backpedal_action.generic.flags  = QMF_GRAYED;
                    753:        s_keys_backpedal_action.generic.x               = 0;
                    754:        s_keys_backpedal_action.generic.y               = y += 9;
                    755:        s_keys_backpedal_action.generic.ownerdraw = DrawKeyBindingFunc;
                    756:        s_keys_backpedal_action.generic.localdata[0] = ++i;
                    757:        s_keys_backpedal_action.generic.name    = bindnames[s_keys_backpedal_action.generic.localdata[0]][1];
1.1.1.2   root      758: 
1.1       root      759:        s_keys_turn_left_action.generic.type    = MTYPE_ACTION;
                    760:        s_keys_turn_left_action.generic.flags  = QMF_GRAYED;
                    761:        s_keys_turn_left_action.generic.x               = 0;
                    762:        s_keys_turn_left_action.generic.y               = y += 9;
                    763:        s_keys_turn_left_action.generic.ownerdraw = DrawKeyBindingFunc;
                    764:        s_keys_turn_left_action.generic.localdata[0] = ++i;
                    765:        s_keys_turn_left_action.generic.name    = bindnames[s_keys_turn_left_action.generic.localdata[0]][1];
1.1.1.2   root      766: 
1.1       root      767:        s_keys_turn_right_action.generic.type   = MTYPE_ACTION;
                    768:        s_keys_turn_right_action.generic.flags  = QMF_GRAYED;
                    769:        s_keys_turn_right_action.generic.x              = 0;
                    770:        s_keys_turn_right_action.generic.y              = y += 9;
                    771:        s_keys_turn_right_action.generic.ownerdraw = DrawKeyBindingFunc;
                    772:        s_keys_turn_right_action.generic.localdata[0] = ++i;
                    773:        s_keys_turn_right_action.generic.name   = bindnames[s_keys_turn_right_action.generic.localdata[0]][1];
1.1.1.2   root      774: 
1.1       root      775:        s_keys_run_action.generic.type  = MTYPE_ACTION;
                    776:        s_keys_run_action.generic.flags  = QMF_GRAYED;
                    777:        s_keys_run_action.generic.x             = 0;
                    778:        s_keys_run_action.generic.y             = y += 9;
                    779:        s_keys_run_action.generic.ownerdraw = DrawKeyBindingFunc;
                    780:        s_keys_run_action.generic.localdata[0] = ++i;
                    781:        s_keys_run_action.generic.name  = bindnames[s_keys_run_action.generic.localdata[0]][1];
1.1.1.2   root      782: 
1.1       root      783:        s_keys_step_left_action.generic.type    = MTYPE_ACTION;
                    784:        s_keys_step_left_action.generic.flags  = QMF_GRAYED;
                    785:        s_keys_step_left_action.generic.x               = 0;
                    786:        s_keys_step_left_action.generic.y               = y += 9;
                    787:        s_keys_step_left_action.generic.ownerdraw = DrawKeyBindingFunc;
                    788:        s_keys_step_left_action.generic.localdata[0] = ++i;
                    789:        s_keys_step_left_action.generic.name    = bindnames[s_keys_step_left_action.generic.localdata[0]][1];
1.1.1.2   root      790: 
1.1       root      791:        s_keys_step_right_action.generic.type   = MTYPE_ACTION;
                    792:        s_keys_step_right_action.generic.flags  = QMF_GRAYED;
                    793:        s_keys_step_right_action.generic.x              = 0;
                    794:        s_keys_step_right_action.generic.y              = y += 9;
                    795:        s_keys_step_right_action.generic.ownerdraw = DrawKeyBindingFunc;
                    796:        s_keys_step_right_action.generic.localdata[0] = ++i;
                    797:        s_keys_step_right_action.generic.name   = bindnames[s_keys_step_right_action.generic.localdata[0]][1];
1.1.1.2   root      798: 
1.1       root      799:        s_keys_sidestep_action.generic.type     = MTYPE_ACTION;
                    800:        s_keys_sidestep_action.generic.flags  = QMF_GRAYED;
                    801:        s_keys_sidestep_action.generic.x                = 0;
                    802:        s_keys_sidestep_action.generic.y                = y += 9;
                    803:        s_keys_sidestep_action.generic.ownerdraw = DrawKeyBindingFunc;
                    804:        s_keys_sidestep_action.generic.localdata[0] = ++i;
                    805:        s_keys_sidestep_action.generic.name     = bindnames[s_keys_sidestep_action.generic.localdata[0]][1];
1.1.1.2   root      806: 
1.1       root      807:        s_keys_look_up_action.generic.type      = MTYPE_ACTION;
                    808:        s_keys_look_up_action.generic.flags  = QMF_GRAYED;
                    809:        s_keys_look_up_action.generic.x         = 0;
                    810:        s_keys_look_up_action.generic.y         = y += 9;
                    811:        s_keys_look_up_action.generic.ownerdraw = DrawKeyBindingFunc;
                    812:        s_keys_look_up_action.generic.localdata[0] = ++i;
                    813:        s_keys_look_up_action.generic.name      = bindnames[s_keys_look_up_action.generic.localdata[0]][1];
1.1.1.2   root      814: 
1.1       root      815:        s_keys_look_down_action.generic.type    = MTYPE_ACTION;
                    816:        s_keys_look_down_action.generic.flags  = QMF_GRAYED;
                    817:        s_keys_look_down_action.generic.x               = 0;
                    818:        s_keys_look_down_action.generic.y               = y += 9;
                    819:        s_keys_look_down_action.generic.ownerdraw = DrawKeyBindingFunc;
                    820:        s_keys_look_down_action.generic.localdata[0] = ++i;
                    821:        s_keys_look_down_action.generic.name    = bindnames[s_keys_look_down_action.generic.localdata[0]][1];
1.1.1.2   root      822: 
1.1       root      823:        s_keys_center_view_action.generic.type  = MTYPE_ACTION;
                    824:        s_keys_center_view_action.generic.flags  = QMF_GRAYED;
                    825:        s_keys_center_view_action.generic.x             = 0;
                    826:        s_keys_center_view_action.generic.y             = y += 9;
                    827:        s_keys_center_view_action.generic.ownerdraw = DrawKeyBindingFunc;
                    828:        s_keys_center_view_action.generic.localdata[0] = ++i;
                    829:        s_keys_center_view_action.generic.name  = bindnames[s_keys_center_view_action.generic.localdata[0]][1];
1.1.1.2   root      830: 
1.1       root      831:        s_keys_mouse_look_action.generic.type   = MTYPE_ACTION;
                    832:        s_keys_mouse_look_action.generic.flags  = QMF_GRAYED;
                    833:        s_keys_mouse_look_action.generic.x              = 0;
                    834:        s_keys_mouse_look_action.generic.y              = y += 9;
                    835:        s_keys_mouse_look_action.generic.ownerdraw = DrawKeyBindingFunc;
                    836:        s_keys_mouse_look_action.generic.localdata[0] = ++i;
                    837:        s_keys_mouse_look_action.generic.name   = bindnames[s_keys_mouse_look_action.generic.localdata[0]][1];
1.1.1.2   root      838: 
1.1       root      839:        s_keys_keyboard_look_action.generic.type        = MTYPE_ACTION;
                    840:        s_keys_keyboard_look_action.generic.flags  = QMF_GRAYED;
                    841:        s_keys_keyboard_look_action.generic.x           = 0;
                    842:        s_keys_keyboard_look_action.generic.y           = y += 9;
                    843:        s_keys_keyboard_look_action.generic.ownerdraw = DrawKeyBindingFunc;
                    844:        s_keys_keyboard_look_action.generic.localdata[0] = ++i;
                    845:        s_keys_keyboard_look_action.generic.name        = bindnames[s_keys_keyboard_look_action.generic.localdata[0]][1];
1.1.1.2   root      846: 
1.1       root      847:        s_keys_move_up_action.generic.type      = MTYPE_ACTION;
                    848:        s_keys_move_up_action.generic.flags  = QMF_GRAYED;
                    849:        s_keys_move_up_action.generic.x         = 0;
                    850:        s_keys_move_up_action.generic.y         = y += 9;
                    851:        s_keys_move_up_action.generic.ownerdraw = DrawKeyBindingFunc;
                    852:        s_keys_move_up_action.generic.localdata[0] = ++i;
                    853:        s_keys_move_up_action.generic.name      = bindnames[s_keys_move_up_action.generic.localdata[0]][1];
1.1.1.2   root      854: 
1.1       root      855:        s_keys_move_down_action.generic.type    = MTYPE_ACTION;
                    856:        s_keys_move_down_action.generic.flags  = QMF_GRAYED;
                    857:        s_keys_move_down_action.generic.x               = 0;
                    858:        s_keys_move_down_action.generic.y               = y += 9;
                    859:        s_keys_move_down_action.generic.ownerdraw = DrawKeyBindingFunc;
                    860:        s_keys_move_down_action.generic.localdata[0] = ++i;
                    861:        s_keys_move_down_action.generic.name    = bindnames[s_keys_move_down_action.generic.localdata[0]][1];
1.1.1.2   root      862: 
1.1       root      863:        s_keys_inventory_action.generic.type    = MTYPE_ACTION;
                    864:        s_keys_inventory_action.generic.flags  = QMF_GRAYED;
                    865:        s_keys_inventory_action.generic.x               = 0;
                    866:        s_keys_inventory_action.generic.y               = y += 9;
                    867:        s_keys_inventory_action.generic.ownerdraw = DrawKeyBindingFunc;
                    868:        s_keys_inventory_action.generic.localdata[0] = ++i;
                    869:        s_keys_inventory_action.generic.name    = bindnames[s_keys_inventory_action.generic.localdata[0]][1];
1.1.1.2   root      870: 
1.1       root      871:        s_keys_inv_use_action.generic.type      = MTYPE_ACTION;
                    872:        s_keys_inv_use_action.generic.flags  = QMF_GRAYED;
                    873:        s_keys_inv_use_action.generic.x         = 0;
                    874:        s_keys_inv_use_action.generic.y         = y += 9;
                    875:        s_keys_inv_use_action.generic.ownerdraw = DrawKeyBindingFunc;
                    876:        s_keys_inv_use_action.generic.localdata[0] = ++i;
                    877:        s_keys_inv_use_action.generic.name      = bindnames[s_keys_inv_use_action.generic.localdata[0]][1];
1.1.1.2   root      878: 
1.1       root      879:        s_keys_inv_drop_action.generic.type     = MTYPE_ACTION;
                    880:        s_keys_inv_drop_action.generic.flags  = QMF_GRAYED;
                    881:        s_keys_inv_drop_action.generic.x                = 0;
                    882:        s_keys_inv_drop_action.generic.y                = y += 9;
                    883:        s_keys_inv_drop_action.generic.ownerdraw = DrawKeyBindingFunc;
                    884:        s_keys_inv_drop_action.generic.localdata[0] = ++i;
                    885:        s_keys_inv_drop_action.generic.name     = bindnames[s_keys_inv_drop_action.generic.localdata[0]][1];
1.1.1.2   root      886: 
1.1       root      887:        s_keys_inv_prev_action.generic.type     = MTYPE_ACTION;
                    888:        s_keys_inv_prev_action.generic.flags  = QMF_GRAYED;
                    889:        s_keys_inv_prev_action.generic.x                = 0;
                    890:        s_keys_inv_prev_action.generic.y                = y += 9;
                    891:        s_keys_inv_prev_action.generic.ownerdraw = DrawKeyBindingFunc;
                    892:        s_keys_inv_prev_action.generic.localdata[0] = ++i;
                    893:        s_keys_inv_prev_action.generic.name     = bindnames[s_keys_inv_prev_action.generic.localdata[0]][1];
1.1.1.2   root      894: 
1.1       root      895:        s_keys_inv_next_action.generic.type     = MTYPE_ACTION;
                    896:        s_keys_inv_next_action.generic.flags  = QMF_GRAYED;
                    897:        s_keys_inv_next_action.generic.x                = 0;
                    898:        s_keys_inv_next_action.generic.y                = y += 9;
                    899:        s_keys_inv_next_action.generic.ownerdraw = DrawKeyBindingFunc;
                    900:        s_keys_inv_next_action.generic.localdata[0] = ++i;
                    901:        s_keys_inv_next_action.generic.name     = bindnames[s_keys_inv_next_action.generic.localdata[0]][1];
1.1.1.2   root      902: 
1.1       root      903:        s_keys_help_computer_action.generic.type        = MTYPE_ACTION;
                    904:        s_keys_help_computer_action.generic.flags  = QMF_GRAYED;
                    905:        s_keys_help_computer_action.generic.x           = 0;
                    906:        s_keys_help_computer_action.generic.y           = y += 9;
                    907:        s_keys_help_computer_action.generic.ownerdraw = DrawKeyBindingFunc;
                    908:        s_keys_help_computer_action.generic.localdata[0] = ++i;
                    909:        s_keys_help_computer_action.generic.name        = bindnames[s_keys_help_computer_action.generic.localdata[0]][1];
1.1.1.2   root      910: 
1.1       root      911:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_attack_action );
                    912:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_change_weapon_action );
                    913:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_walk_forward_action );
                    914:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_backpedal_action );
                    915:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_left_action );
                    916:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_right_action );
                    917:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_run_action );
                    918:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_left_action );
                    919:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_right_action );
                    920:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_sidestep_action );
                    921:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_up_action );
                    922:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_down_action );
                    923:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_center_view_action );
                    924:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_mouse_look_action );
                    925:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_keyboard_look_action );
                    926:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_up_action );
                    927:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_down_action );
1.1.1.2   root      928: 
1.1       root      929:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inventory_action );
                    930:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_use_action );
                    931:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_drop_action );
                    932:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_prev_action );
                    933:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_next_action );
1.1.1.2   root      934: 
1.1       root      935:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_help_computer_action );
                    936:        
                    937:        Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
                    938:        Menu_Center( &s_keys_menu );
                    939: }
1.1.1.2   root      940: 
1.1       root      941: static void Keys_MenuDraw (void)
                    942: {
                    943:        Menu_AdjustCursor( &s_keys_menu, 1 );
                    944:        Menu_Draw( &s_keys_menu );
                    945: }
1.1.1.2   root      946: 
1.1       root      947: static const char *Keys_MenuKey( int key )
                    948: {
                    949:        menuaction_s *item = ( menuaction_s * ) Menu_ItemAtCursor( &s_keys_menu );
1.1.1.2   root      950: 
1.1       root      951:        if ( bind_grab )
                    952:        {       
                    953:                if ( key != K_ESCAPE && key != '`' )
                    954:                {
                    955:                        char cmd[1024];
1.1.1.2   root      956: 
1.1       root      957:                        Com_sprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(key), bindnames[item->generic.localdata[0]][0]);
                    958:                        Cbuf_InsertText (cmd);
                    959:                }
                    960:                
                    961:                Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
                    962:                bind_grab = false;
                    963:                return menu_out_sound;
                    964:        }
1.1.1.2   root      965: 
1.1       root      966:        switch ( key )
                    967:        {
                    968:        case K_KP_ENTER:
                    969:        case K_ENTER:
                    970:                KeyBindingFunc( item );
                    971:                return menu_in_sound;
                    972:        case K_BACKSPACE:               // delete bindings
                    973:        case K_DEL:                             // delete bindings
                    974:        case K_KP_DEL:
                    975:                M_UnbindCommand( bindnames[item->generic.localdata[0]][0] );
                    976:                return menu_out_sound;
                    977:        default:
                    978:                return Default_MenuKey( &s_keys_menu, key );
                    979:        }
                    980: }
1.1.1.2   root      981: 
1.1       root      982: void M_Menu_Keys_f (void)
                    983: {
                    984:        Keys_MenuInit();
                    985:        M_PushMenu( Keys_MenuDraw, Keys_MenuKey );
                    986: }
1.1.1.2   root      987: 
                    988: 
1.1       root      989: /*
                    990: =======================================================================
1.1.1.2   root      991: 
1.1       root      992: CONTROLS MENU
1.1.1.2   root      993: 
1.1       root      994: =======================================================================
                    995: */
                    996: static cvar_t *win_noalttab;
                    997: extern cvar_t *in_joystick;
1.1.1.2   root      998: 
1.1       root      999: static menuframework_s s_options_menu;
                   1000: static menuaction_s            s_options_defaults_action;
                   1001: static menuaction_s            s_options_customize_options_action;
                   1002: static menuslider_s            s_options_sensitivity_slider;
                   1003: static menulist_s              s_options_freelook_box;
                   1004: static menulist_s              s_options_noalttab_box;
                   1005: static menulist_s              s_options_alwaysrun_box;
                   1006: static menulist_s              s_options_invertmouse_box;
                   1007: static menulist_s              s_options_lookspring_box;
                   1008: static menulist_s              s_options_lookstrafe_box;
                   1009: static menulist_s              s_options_crosshair_box;
                   1010: static menuslider_s            s_options_sfxvolume_slider;
                   1011: static menulist_s              s_options_joystick_box;
                   1012: static menulist_s              s_options_cdvolume_box;
                   1013: static menulist_s              s_options_quality_list;
                   1014: static menulist_s              s_options_compatibility_list;
                   1015: static menulist_s              s_options_console_action;
                   1016: 
                   1017: static void CrosshairFunc( void *unused )
                   1018: {
                   1019:        Cvar_SetValue( "crosshair", s_options_crosshair_box.curvalue );
                   1020: }
                   1021: 
                   1022: static void JoystickFunc( void *unused )
                   1023: {
                   1024:        Cvar_SetValue( "in_joystick", s_options_joystick_box.curvalue );
                   1025: }
1.1.1.2   root     1026: 
1.1       root     1027: static void CustomizeControlsFunc( void *unused )
                   1028: {
                   1029:        M_Menu_Keys_f();
                   1030: }
1.1.1.2   root     1031: 
1.1       root     1032: static void AlwaysRunFunc( void *unused )
                   1033: {
                   1034:        Cvar_SetValue( "cl_run", s_options_alwaysrun_box.curvalue );
                   1035: }
1.1.1.2   root     1036: 
1.1       root     1037: static void FreeLookFunc( void *unused )
                   1038: {
                   1039:        Cvar_SetValue( "freelook", s_options_freelook_box.curvalue );
                   1040: }
1.1.1.2   root     1041: 
1.1       root     1042: static void MouseSpeedFunc( void *unused )
                   1043: {
                   1044:        Cvar_SetValue( "sensitivity", s_options_sensitivity_slider.curvalue / 2.0F );
                   1045: }
1.1.1.2   root     1046: 
1.1       root     1047: static void NoAltTabFunc( void *unused )
                   1048: {
                   1049:        Cvar_SetValue( "win_noalttab", s_options_noalttab_box.curvalue );
                   1050: }
1.1.1.2   root     1051: 
1.1       root     1052: static float ClampCvar( float min, float max, float value )
                   1053: {
                   1054:        if ( value < min ) return min;
                   1055:        if ( value > max ) return max;
                   1056:        return value;
                   1057: }
                   1058: 
                   1059: static void ControlsSetMenuItemValues( void )
                   1060: {
                   1061:        s_options_sfxvolume_slider.curvalue             = Cvar_VariableValue( "s_volume" ) * 10;
                   1062:        s_options_cdvolume_box.curvalue                 = !Cvar_VariableValue("cd_nocd");
                   1063:        s_options_quality_list.curvalue                 = !Cvar_VariableValue( "s_loadas8bit" );
                   1064:        s_options_sensitivity_slider.curvalue   = ( sensitivity->value ) * 2;
                   1065: 
                   1066:        Cvar_SetValue( "cl_run", ClampCvar( 0, 1, cl_run->value ) );
                   1067:        s_options_alwaysrun_box.curvalue                = cl_run->value;
                   1068: 
                   1069:        s_options_invertmouse_box.curvalue              = m_pitch->value < 0;
                   1070: 
                   1071:        Cvar_SetValue( "lookspring", ClampCvar( 0, 1, lookspring->value ) );
                   1072:        s_options_lookspring_box.curvalue               = lookspring->value;
                   1073: 
                   1074:        Cvar_SetValue( "lookstrafe", ClampCvar( 0, 1, lookstrafe->value ) );
                   1075:        s_options_lookstrafe_box.curvalue               = lookstrafe->value;
                   1076: 
                   1077:        Cvar_SetValue( "freelook", ClampCvar( 0, 1, freelook->value ) );
                   1078:        s_options_freelook_box.curvalue                 = freelook->value;
                   1079: 
                   1080:        Cvar_SetValue( "crosshair", ClampCvar( 0, 3, crosshair->value ) );
                   1081:        s_options_crosshair_box.curvalue                = crosshair->value;
                   1082: 
                   1083:        Cvar_SetValue( "in_joystick", ClampCvar( 0, 1, in_joystick->value ) );
                   1084:        s_options_joystick_box.curvalue         = in_joystick->value;
                   1085: 
                   1086:        s_options_noalttab_box.curvalue                 = win_noalttab->value;
                   1087: }
1.1.1.2   root     1088: 
1.1       root     1089: static void ControlsResetDefaultsFunc( void *unused )
                   1090: {
                   1091:        Cbuf_AddText ("exec default.cfg\n");
                   1092:        Cbuf_Execute();
                   1093: 
                   1094:        ControlsSetMenuItemValues();
                   1095: }
1.1.1.2   root     1096: 
1.1       root     1097: static void InvertMouseFunc( void *unused )
                   1098: {
                   1099:        Cvar_SetValue( "m_pitch", -m_pitch->value );
                   1100: }
1.1.1.2   root     1101: 
1.1       root     1102: static void LookspringFunc( void *unused )
                   1103: {
                   1104:        Cvar_SetValue( "lookspring", !lookspring->value );
                   1105: }
1.1.1.2   root     1106: 
1.1       root     1107: static void LookstrafeFunc( void *unused )
                   1108: {
                   1109:        Cvar_SetValue( "lookstrafe", !lookstrafe->value );
                   1110: }
1.1.1.2   root     1111: 
1.1       root     1112: static void UpdateVolumeFunc( void *unused )
                   1113: {
                   1114:        Cvar_SetValue( "s_volume", s_options_sfxvolume_slider.curvalue / 10 );
                   1115: }
                   1116: 
                   1117: static void UpdateCDVolumeFunc( void *unused )
                   1118: {
                   1119:        Cvar_SetValue( "cd_nocd", !s_options_cdvolume_box.curvalue );
                   1120: }
                   1121: 
                   1122: static void ConsoleFunc( void *unused )
                   1123: {
                   1124:        /*
                   1125:        ** the proper way to do this is probably to have ToggleConsole_f accept a parameter
                   1126:        */
                   1127:        extern void Key_ClearTyping( void );
                   1128: 
                   1129:        if ( cl.attractloop )
                   1130:        {
                   1131:                Cbuf_AddText ("killserver\n");
                   1132:                return;
                   1133:        }
                   1134: 
                   1135:        Key_ClearTyping ();
                   1136:        Con_ClearNotify ();
                   1137: 
                   1138:        M_ForceMenuOff ();
                   1139:        cls.key_dest = key_console;
                   1140: }
                   1141: 
                   1142: static void UpdateSoundQualityFunc( void *unused )
                   1143: {
                   1144:        if ( s_options_quality_list.curvalue )
                   1145:        {
                   1146:                Cvar_SetValue( "s_khz", 22 );
                   1147:                Cvar_SetValue( "s_loadas8bit", false );
                   1148:        }
                   1149:        else
                   1150:        {
                   1151:                Cvar_SetValue( "s_khz", 11 );
                   1152:                Cvar_SetValue( "s_loadas8bit", true );
                   1153:        }
                   1154:        
                   1155:        Cvar_SetValue( "s_primary", s_options_compatibility_list.curvalue );
                   1156: 
                   1157:        M_DrawTextBox( 8, 120 - 48, 36, 3 );
                   1158:        M_Print( 16 + 16, 120 - 48 + 8,  "Restarting the sound system. This" );
                   1159:        M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
                   1160:        M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
                   1161: 
                   1162:        // the text box won't show up unless we do a buffer swap
                   1163:        re.EndFrame();
                   1164: 
                   1165:        CL_Snd_Restart_f();
                   1166: }
                   1167: 
                   1168: void Options_MenuInit( void )
                   1169: {
                   1170:        static const char *cd_music_items[] =
                   1171:        {
                   1172:                "disabled",
                   1173:                "enabled",
                   1174:                0
                   1175:        };
                   1176:        static const char *quality_items[] =
                   1177:        {
                   1178:                "low", "high", 0
                   1179:        };
                   1180: 
                   1181:        static const char *compatibility_items[] =
                   1182:        {
                   1183:                "max compatibility", "max performance", 0
                   1184:        };
                   1185: 
                   1186:        static const char *yesno_names[] =
                   1187:        {
                   1188:                "no",
                   1189:                "yes",
                   1190:                0
                   1191:        };
1.1.1.2   root     1192: 
1.1       root     1193:        static const char *crosshair_names[] =
                   1194:        {
                   1195:                "none",
                   1196:                "cross",
                   1197:                "dot",
                   1198:                "angle",
                   1199:                0
                   1200:        };
1.1.1.2   root     1201: 
1.1       root     1202:        win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
1.1.1.2   root     1203: 
1.1       root     1204:        /*
                   1205:        ** configure controls menu and menu items
                   1206:        */
                   1207:        s_options_menu.x = viddef.width / 2;
                   1208:        s_options_menu.y = viddef.height / 2 - 58;
                   1209:        s_options_menu.nitems = 0;
                   1210: 
                   1211:        s_options_sfxvolume_slider.generic.type = MTYPE_SLIDER;
                   1212:        s_options_sfxvolume_slider.generic.x    = 0;
                   1213:        s_options_sfxvolume_slider.generic.y    = 0;
                   1214:        s_options_sfxvolume_slider.generic.name = "effects volume";
                   1215:        s_options_sfxvolume_slider.generic.callback     = UpdateVolumeFunc;
                   1216:        s_options_sfxvolume_slider.minvalue             = 0;
                   1217:        s_options_sfxvolume_slider.maxvalue             = 10;
                   1218:        s_options_sfxvolume_slider.curvalue             = Cvar_VariableValue( "s_volume" ) * 10;
                   1219: 
                   1220:        s_options_cdvolume_box.generic.type     = MTYPE_SPINCONTROL;
                   1221:        s_options_cdvolume_box.generic.x                = 0;
                   1222:        s_options_cdvolume_box.generic.y                = 10;
                   1223:        s_options_cdvolume_box.generic.name     = "CD music";
                   1224:        s_options_cdvolume_box.generic.callback = UpdateCDVolumeFunc;
                   1225:        s_options_cdvolume_box.itemnames                = cd_music_items;
                   1226:        s_options_cdvolume_box.curvalue                 = !Cvar_VariableValue("cd_nocd");
                   1227: 
                   1228:        s_options_quality_list.generic.type     = MTYPE_SPINCONTROL;
                   1229:        s_options_quality_list.generic.x                = 0;
                   1230:        s_options_quality_list.generic.y                = 20;;
                   1231:        s_options_quality_list.generic.name             = "sound quality";
                   1232:        s_options_quality_list.generic.callback = UpdateSoundQualityFunc;
                   1233:        s_options_quality_list.itemnames                = quality_items;
                   1234:        s_options_quality_list.curvalue                 = !Cvar_VariableValue( "s_loadas8bit" );
                   1235: 
                   1236:        s_options_compatibility_list.generic.type       = MTYPE_SPINCONTROL;
                   1237:        s_options_compatibility_list.generic.x          = 0;
                   1238:        s_options_compatibility_list.generic.y          = 30;
                   1239:        s_options_compatibility_list.generic.name       = "sound compatibility";
                   1240:        s_options_compatibility_list.generic.callback = UpdateSoundQualityFunc;
                   1241:        s_options_compatibility_list.itemnames          = compatibility_items;
                   1242:        s_options_compatibility_list.curvalue           = Cvar_VariableValue( "s_primary" );
                   1243: 
                   1244:        s_options_sensitivity_slider.generic.type       = MTYPE_SLIDER;
                   1245:        s_options_sensitivity_slider.generic.x          = 0;
                   1246:        s_options_sensitivity_slider.generic.y          = 50;
                   1247:        s_options_sensitivity_slider.generic.name       = "mouse speed";
                   1248:        s_options_sensitivity_slider.generic.callback = MouseSpeedFunc;
                   1249:        s_options_sensitivity_slider.minvalue           = 2;
                   1250:        s_options_sensitivity_slider.maxvalue           = 22;
1.1.1.2   root     1251: 
1.1       root     1252:        s_options_alwaysrun_box.generic.type = MTYPE_SPINCONTROL;
                   1253:        s_options_alwaysrun_box.generic.x       = 0;
                   1254:        s_options_alwaysrun_box.generic.y       = 60;
                   1255:        s_options_alwaysrun_box.generic.name    = "always run";
                   1256:        s_options_alwaysrun_box.generic.callback = AlwaysRunFunc;
                   1257:        s_options_alwaysrun_box.itemnames = yesno_names;
1.1.1.2   root     1258: 
1.1       root     1259:        s_options_invertmouse_box.generic.type = MTYPE_SPINCONTROL;
                   1260:        s_options_invertmouse_box.generic.x     = 0;
                   1261:        s_options_invertmouse_box.generic.y     = 70;
                   1262:        s_options_invertmouse_box.generic.name  = "invert mouse";
                   1263:        s_options_invertmouse_box.generic.callback = InvertMouseFunc;
                   1264:        s_options_invertmouse_box.itemnames = yesno_names;
1.1.1.2   root     1265: 
1.1       root     1266:        s_options_lookspring_box.generic.type = MTYPE_SPINCONTROL;
                   1267:        s_options_lookspring_box.generic.x      = 0;
                   1268:        s_options_lookspring_box.generic.y      = 80;
                   1269:        s_options_lookspring_box.generic.name   = "lookspring";
                   1270:        s_options_lookspring_box.generic.callback = LookspringFunc;
                   1271:        s_options_lookspring_box.itemnames = yesno_names;
1.1.1.2   root     1272: 
1.1       root     1273:        s_options_lookstrafe_box.generic.type = MTYPE_SPINCONTROL;
                   1274:        s_options_lookstrafe_box.generic.x      = 0;
                   1275:        s_options_lookstrafe_box.generic.y      = 90;
                   1276:        s_options_lookstrafe_box.generic.name   = "lookstrafe";
                   1277:        s_options_lookstrafe_box.generic.callback = LookstrafeFunc;
                   1278:        s_options_lookstrafe_box.itemnames = yesno_names;
1.1.1.2   root     1279: 
1.1       root     1280:        s_options_freelook_box.generic.type = MTYPE_SPINCONTROL;
                   1281:        s_options_freelook_box.generic.x        = 0;
                   1282:        s_options_freelook_box.generic.y        = 100;
                   1283:        s_options_freelook_box.generic.name     = "free look";
                   1284:        s_options_freelook_box.generic.callback = FreeLookFunc;
                   1285:        s_options_freelook_box.itemnames = yesno_names;
                   1286: 
                   1287:        s_options_crosshair_box.generic.type = MTYPE_SPINCONTROL;
                   1288:        s_options_crosshair_box.generic.x       = 0;
                   1289:        s_options_crosshair_box.generic.y       = 110;
                   1290:        s_options_crosshair_box.generic.name    = "crosshair";
                   1291:        s_options_crosshair_box.generic.callback = CrosshairFunc;
                   1292:        s_options_crosshair_box.itemnames = crosshair_names;
                   1293: /*
                   1294:        s_options_noalttab_box.generic.type = MTYPE_SPINCONTROL;
                   1295:        s_options_noalttab_box.generic.x        = 0;
                   1296:        s_options_noalttab_box.generic.y        = 110;
                   1297:        s_options_noalttab_box.generic.name     = "disable alt-tab";
                   1298:        s_options_noalttab_box.generic.callback = NoAltTabFunc;
                   1299:        s_options_noalttab_box.itemnames = yesno_names;
                   1300: */
                   1301:        s_options_joystick_box.generic.type = MTYPE_SPINCONTROL;
                   1302:        s_options_joystick_box.generic.x        = 0;
                   1303:        s_options_joystick_box.generic.y        = 120;
                   1304:        s_options_joystick_box.generic.name     = "use joystick";
                   1305:        s_options_joystick_box.generic.callback = JoystickFunc;
                   1306:        s_options_joystick_box.itemnames = yesno_names;
                   1307: 
                   1308:        s_options_customize_options_action.generic.type = MTYPE_ACTION;
                   1309:        s_options_customize_options_action.generic.x            = 0;
                   1310:        s_options_customize_options_action.generic.y            = 140;
                   1311:        s_options_customize_options_action.generic.name = "customize controls";
                   1312:        s_options_customize_options_action.generic.callback = CustomizeControlsFunc;
1.1.1.2   root     1313: 
1.1       root     1314:        s_options_defaults_action.generic.type  = MTYPE_ACTION;
                   1315:        s_options_defaults_action.generic.x             = 0;
                   1316:        s_options_defaults_action.generic.y             = 150;
                   1317:        s_options_defaults_action.generic.name  = "reset defaults";
                   1318:        s_options_defaults_action.generic.callback = ControlsResetDefaultsFunc;
                   1319: 
                   1320:        s_options_console_action.generic.type   = MTYPE_ACTION;
                   1321:        s_options_console_action.generic.x              = 0;
                   1322:        s_options_console_action.generic.y              = 160;
                   1323:        s_options_console_action.generic.name   = "go to console";
                   1324:        s_options_console_action.generic.callback = ConsoleFunc;
                   1325: 
                   1326:        ControlsSetMenuItemValues();
                   1327: 
                   1328:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_sfxvolume_slider );
                   1329:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_cdvolume_box );
                   1330:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_quality_list );
                   1331:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_compatibility_list );
                   1332:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_sensitivity_slider );
                   1333:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_alwaysrun_box );
                   1334:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_invertmouse_box );
                   1335:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookspring_box );
                   1336:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookstrafe_box );
                   1337:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_freelook_box );
                   1338:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_crosshair_box );
                   1339:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_joystick_box );
                   1340:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_customize_options_action );
                   1341:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_defaults_action );
                   1342:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_console_action );
                   1343: }
1.1.1.2   root     1344: 
1.1       root     1345: void Options_MenuDraw (void)
                   1346: {
                   1347:        M_Banner( "m_banner_options" );
                   1348:        Menu_AdjustCursor( &s_options_menu, 1 );
                   1349:        Menu_Draw( &s_options_menu );
                   1350: }
1.1.1.2   root     1351: 
1.1       root     1352: const char *Options_MenuKey( int key )
                   1353: {
                   1354:        return Default_MenuKey( &s_options_menu, key );
                   1355: }
1.1.1.2   root     1356: 
1.1       root     1357: void M_Menu_Options_f (void)
                   1358: {
                   1359:        Options_MenuInit();
                   1360:        M_PushMenu ( Options_MenuDraw, Options_MenuKey );
                   1361: }
1.1.1.2   root     1362: 
1.1       root     1363: /*
                   1364: =======================================================================
1.1.1.2   root     1365: 
1.1       root     1366: VIDEO MENU
1.1.1.2   root     1367: 
1.1       root     1368: =======================================================================
                   1369: */
1.1.1.2   root     1370: 
1.1       root     1371: void M_Menu_Video_f (void)
                   1372: {
                   1373:        VID_MenuInit();
                   1374:        M_PushMenu( VID_MenuDraw, VID_MenuKey );
                   1375: }
1.1.1.2   root     1376: 
1.1       root     1377: /*
                   1378: =============================================================================
                   1379: 
                   1380: END GAME MENU
                   1381: 
                   1382: =============================================================================
                   1383: */
                   1384: static int credits_start_time;
1.1.1.2   root     1385: static const char **credits;
                   1386: static char *creditsIndex[256];
                   1387: static char *creditsBuffer;
                   1388: static const char *idcredits[] =
1.1       root     1389: {
                   1390:        "+QUAKE II BY ID SOFTWARE",
                   1391:        "",
                   1392:        "+PROGRAMMING",
                   1393:        "John Carmack",
                   1394:        "John Cash",
                   1395:        "Brian Hook",
                   1396:        "",
                   1397:        "+ART",
                   1398:        "Adrian Carmack",
                   1399:        "Kevin Cloud",
                   1400:        "Paul Steed",
                   1401:        "",
                   1402:        "+LEVEL DESIGN",
                   1403:        "Tim Willits",
                   1404:        "American McGee",
                   1405:        "Christian Antkow",
                   1406:        "Paul Jaquays",
                   1407:        "Brandon James",
                   1408:        "",
                   1409:        "+BIZ",
                   1410:        "Todd Hollenshead",
                   1411:        "Barrett (Bear) Alexander",
                   1412:        "Donna Jackson",
                   1413:        "",
                   1414:        "",
                   1415:        "+SPECIAL THANKS",
                   1416:        "Ben Donges for beta testing",
                   1417:        "",
                   1418:        "",
                   1419:        "",
                   1420:        "",
                   1421:        "",
                   1422:        "",
                   1423:        "+ADDITIONAL SUPPORT",
                   1424:        "",
                   1425:        "+LINUX PORT AND CTF",
                   1426:        "Dave \"Zoid\" Kirsch",
                   1427:        "",
                   1428:        "+CINEMATIC SEQUENCES",
                   1429:        "Ending Cinematic by Blur Studio - ",
                   1430:        "Venice, CA",
                   1431:        "",
                   1432:        "Environment models for Introduction",
                   1433:        "Cinematic by Karl Dolgener",
                   1434:        "",
                   1435:        "Assistance with environment design",
                   1436:        "by Cliff Iwai",
                   1437:        "",
                   1438:        "+SOUND EFFECTS AND MUSIC",
                   1439:        "Sound Design by Soundelux Media Labs.",
                   1440:        "Music Composed and Produced by",
                   1441:        "Soundelux Media Labs.  Special thanks",
                   1442:        "to Bill Brown, Tom Ozanich, Brian",
                   1443:        "Celano, Jeff Eisner, and The Soundelux",
                   1444:        "Players.",
                   1445:        "",
                   1446:        "\"Level Music\" by Sonic Mayhem",
                   1447:        "www.sonicmayhem.com",
                   1448:        "",
                   1449:        "\"Quake II Theme Song\"",
                   1450:        "(C) 1997 Rob Zombie. All Rights",
                   1451:        "Reserved.",
                   1452:        "",
                   1453:        "Track 10 (\"Climb\") by Jer Sypult",
                   1454:        "",
                   1455:        "Voice of computers by",
                   1456:        "Carly Staehlin-Taylor",
                   1457:        "",
                   1458:        "+THANKS TO ACTIVISION",
                   1459:        "+IN PARTICULAR:",
                   1460:        "",
                   1461:        "John Tam",
                   1462:        "Steve Rosenthal",
                   1463:        "Marty Stratton",
                   1464:        "Henk Hartong",
                   1465:        "",
                   1466:        "Quake II(tm) (C)1997 Id Software, Inc.",
                   1467:        "All Rights Reserved.  Distributed by",
                   1468:        "Activision, Inc. under license.",
                   1469:        "Quake II(tm), the Id Software name,",
                   1470:        "the \"Q II\"(tm) logo and id(tm)",
                   1471:        "logo are trademarks of Id Software,",
                   1472:        "Inc. Activision(R) is a registered",
                   1473:        "trademark of Activision, Inc. All",
                   1474:        "other trademarks and trade names are",
                   1475:        "properties of their respective owners.",
                   1476:        0
                   1477: };
                   1478: 
1.1.1.2   root     1479: static const char *xatcredits[] =
                   1480: {
                   1481:        "+QUAKE II MISSION PACK: THE RECKONING",
                   1482:        "+BY",
                   1483:        "+XATRIX ENTERTAINMENT, INC.",
                   1484:        "",
                   1485:        "+DESIGN AND DIRECTION",
                   1486:        "Drew Markham",
                   1487:        "",
                   1488:        "+PRODUCED BY",
                   1489:        "Greg Goodrich",
                   1490:        "",
                   1491:        "+PROGRAMMING",
                   1492:        "Rafael Paiz",
                   1493:        "",
                   1494:        "+LEVEL DESIGN / ADDITIONAL GAME DESIGN",
                   1495:        "Alex Mayberry",
                   1496:        "",
                   1497:        "+LEVEL DESIGN",
                   1498:        "Mal Blackwell",
                   1499:        "Dan Koppel",
                   1500:        "",
                   1501:        "+ART DIRECTION",
                   1502:        "Michael \"Maxx\" Kaufman",
                   1503:        "",
                   1504:        "+COMPUTER GRAPHICS SUPERVISOR AND",
                   1505:        "+CHARACTER ANIMATION DIRECTION",
                   1506:        "Barry Dempsey",
                   1507:        "",
                   1508:        "+SENIOR ANIMATOR AND MODELER",
                   1509:        "Jason Hoover",
                   1510:        "",
                   1511:        "+CHARACTER ANIMATION AND",
                   1512:        "+MOTION CAPTURE SPECIALIST",
                   1513:        "Amit Doron",
                   1514:        "",
                   1515:        "+ART",
                   1516:        "Claire Praderie-Markham",
                   1517:        "Viktor Antonov",
                   1518:        "Corky Lehmkuhl",
                   1519:        "",
                   1520:        "+INTRODUCTION ANIMATION",
                   1521:        "Dominique Drozdz",
                   1522:        "",
                   1523:        "+ADDITIONAL LEVEL DESIGN",
                   1524:        "Aaron Barber",
                   1525:        "Rhett Baldwin",
                   1526:        "",
                   1527:        "+3D CHARACTER ANIMATION TOOLS",
                   1528:        "Gerry Tyra, SA Technology",
                   1529:        "",
                   1530:        "+ADDITIONAL EDITOR TOOL PROGRAMMING",
                   1531:        "Robert Duffy",
                   1532:        "",
                   1533:        "+ADDITIONAL PROGRAMMING",
                   1534:        "Ryan Feltrin",
                   1535:        "",
                   1536:        "+PRODUCTION COORDINATOR",
                   1537:        "Victoria Sylvester",
                   1538:        "",
                   1539:        "+SOUND DESIGN",
                   1540:        "Gary Bradfield",
                   1541:        "",
                   1542:        "+MUSIC BY",
                   1543:        "Sonic Mayhem",
                   1544:        "",
                   1545:        "",
                   1546:        "",
                   1547:        "+SPECIAL THANKS",
                   1548:        "+TO",
                   1549:        "+OUR FRIENDS AT ID SOFTWARE",
                   1550:        "",
                   1551:        "John Carmack",
                   1552:        "John Cash",
                   1553:        "Brian Hook",
                   1554:        "Adrian Carmack",
                   1555:        "Kevin Cloud",
                   1556:        "Paul Steed",
                   1557:        "Tim Willits",
                   1558:        "Christian Antkow",
                   1559:        "Paul Jaquays",
                   1560:        "Brandon James",
                   1561:        "Todd Hollenshead",
                   1562:        "Barrett (Bear) Alexander",
                   1563:        "Dave \"Zoid\" Kirsch",
                   1564:        "Donna Jackson",
                   1565:        "",
                   1566:        "",
                   1567:        "",
                   1568:        "+THANKS TO ACTIVISION",
                   1569:        "+IN PARTICULAR:",
                   1570:        "",
                   1571:        "Marty Stratton",
                   1572:        "Henk \"The Original Ripper\" Hartong",
                   1573:        "Kevin Kraff",
                   1574:        "Jamey Gottlieb",
                   1575:        "Chris Hepburn",
                   1576:        "",
                   1577:        "+AND THE GAME TESTERS",
                   1578:        "",
                   1579:        "Tim Vanlaw",
                   1580:        "Doug Jacobs",
                   1581:        "Steven Rosenthal",
                   1582:        "David Baker",
                   1583:        "Chris Campbell",
                   1584:        "Aaron Casillas",
                   1585:        "Steve Elwell",
                   1586:        "Derek Johnstone",
                   1587:        "Igor Krinitskiy",
                   1588:        "Samantha Lee",
                   1589:        "Michael Spann",
                   1590:        "Chris Toft",
                   1591:        "Juan Valdes",
                   1592:        "",
                   1593:        "+THANKS TO INTERGRAPH COMPUTER SYTEMS",
                   1594:        "+IN PARTICULAR:",
                   1595:        "",
                   1596:        "Michael T. Nicolaou",
                   1597:        "",
                   1598:        "",
                   1599:        "Quake II Mission Pack: The Reckoning",
                   1600:        "(tm) (C)1998 Id Software, Inc. All",
                   1601:        "Rights Reserved. Developed by Xatrix",
                   1602:        "Entertainment, Inc. for Id Software,",
                   1603:        "Inc. Distributed by Activision Inc.",
                   1604:        "under license. Quake(R) is a",
                   1605:        "registered trademark of Id Software,",
                   1606:        "Inc. Quake II Mission Pack: The",
                   1607:        "Reckoning(tm), Quake II(tm), the Id",
                   1608:        "Software name, the \"Q II\"(tm) logo",
                   1609:        "and id(tm) logo are trademarks of Id",
                   1610:        "Software, Inc. Activision(R) is a",
                   1611:        "registered trademark of Activision,",
                   1612:        "Inc. Xatrix(R) is a registered",
                   1613:        "trademark of Xatrix Entertainment,",
                   1614:        "Inc. All other trademarks and trade",
                   1615:        "names are properties of their",
                   1616:        "respective owners.",
                   1617:        0
                   1618: };
                   1619: 
1.1.1.3 ! root     1620: static const char *roguecredits[] =
        !          1621: {
        !          1622:        "+QUAKE II MISSION PACK 2: GROUND ZERO",
        !          1623:        "+BY",
        !          1624:        "+ROGUE ENTERTAINMENT, INC.",
        !          1625:        "",
        !          1626:        "+PRODUCED BY",
        !          1627:        "Jim Molinets",
        !          1628:        "",
        !          1629:        "+PROGRAMMING",
        !          1630:        "Peter Mack",
        !          1631:        "Patrick Magruder",
        !          1632:        "",
        !          1633:        "+LEVEL DESIGN",
        !          1634:        "Jim Molinets",
        !          1635:        "Cameron Lamprecht",
        !          1636:        "Berenger Fish",
        !          1637:        "Robert Selitto",
        !          1638:        "Steve Tietze",
        !          1639:        "Steve Thoms",
        !          1640:        "",
        !          1641:        "+ART DIRECTION",
        !          1642:        "Rich Fleider",
        !          1643:        "",
        !          1644:        "+ART",
        !          1645:        "Rich Fleider",
        !          1646:        "Steve Maines",
        !          1647:        "Won Choi",
        !          1648:        "",
        !          1649:        "+ANIMATION SEQUENCES",
        !          1650:        "Creat Studios",
        !          1651:        "Steve Maines",
        !          1652:        "",
        !          1653:        "+ADDITIONAL LEVEL DESIGN",
        !          1654:        "Rich Fleider",
        !          1655:        "Steve Maines",
        !          1656:        "Peter Mack",
        !          1657:        "",
        !          1658:        "+SOUND",
        !          1659:        "James Grunke",
        !          1660:        "",
        !          1661:        "+GROUND ZERO THEME",
        !          1662:        "+AND",
        !          1663:        "+MUSIC BY",
        !          1664:        "Sonic Mayhem",
        !          1665:        "",
        !          1666:        "+VWEP MODELS",
        !          1667:        "Brent \"Hentai\" Dill",
        !          1668:        "",
        !          1669:        "",
        !          1670:        "",
        !          1671:        "+SPECIAL THANKS",
        !          1672:        "+TO",
        !          1673:        "+OUR FRIENDS AT ID SOFTWARE",
        !          1674:        "",
        !          1675:        "John Carmack",
        !          1676:        "John Cash",
        !          1677:        "Brian Hook",
        !          1678:        "Adrian Carmack",
        !          1679:        "Kevin Cloud",
        !          1680:        "Paul Steed",
        !          1681:        "Tim Willits",
        !          1682:        "Christian Antkow",
        !          1683:        "Paul Jaquays",
        !          1684:        "Brandon James",
        !          1685:        "Todd Hollenshead",
        !          1686:        "Barrett (Bear) Alexander",
        !          1687:        "Katherine Anna Kang",
        !          1688:        "Donna Jackson",
        !          1689:        "Dave \"Zoid\" Kirsch",
        !          1690:        "",
        !          1691:        "",
        !          1692:        "",
        !          1693:        "+THANKS TO ACTIVISION",
        !          1694:        "+IN PARTICULAR:",
        !          1695:        "",
        !          1696:        "Marty Stratton",
        !          1697:        "Henk Hartong",
        !          1698:        "Mitch Lasky",
        !          1699:        "Steve Rosenthal",
        !          1700:        "Steve Elwell",
        !          1701:        "",
        !          1702:        "+AND THE GAME TESTERS",
        !          1703:        "",
        !          1704:        "The Ranger Clan",
        !          1705:        "Dave \"Zoid\" Kirsch",
        !          1706:        "Nihilistic Software",
        !          1707:        "Robert Duffy",
        !          1708:        "",
        !          1709:        "And Countless Others",
        !          1710:        "",
        !          1711:        "",
        !          1712:        "",
        !          1713:        "Quake II Mission Pack 2: Ground Zero",
        !          1714:        "(tm) (C)1998 Id Software, Inc. All",
        !          1715:        "Rights Reserved. Developed by Rogue",
        !          1716:        "Entertainment, Inc. for Id Software,",
        !          1717:        "Inc. Distributed by Activision Inc.",
        !          1718:        "under license. Quake(R) is a",
        !          1719:        "registered trademark of Id Software,",
        !          1720:        "Inc. Quake II Mission Pack 2: Ground",
        !          1721:        "Zero(tm), Quake II(tm), the Id",
        !          1722:        "Software name, the \"Q II\"(tm) logo",
        !          1723:        "and id(tm) logo are trademarks of Id",
        !          1724:        "Software, Inc. Activision(R) is a",
        !          1725:        "registered trademark of Activision,",
        !          1726:        "Inc. Rogue(R) is a registered",
        !          1727:        "trademark of Rogue Entertainment,",
        !          1728:        "Inc. All other trademarks and trade",
        !          1729:        "names are properties of their",
        !          1730:        "respective owners.",
        !          1731:        0
        !          1732: };
        !          1733: 
        !          1734: 
1.1       root     1735: void M_Credits_MenuDraw( void )
                   1736: {
                   1737:        int i, y;
                   1738: 
                   1739:        /*
                   1740:        ** draw the credits
                   1741:        */
                   1742:        for ( i = 0, y = viddef.height - ( ( cls.realtime - credits_start_time ) / 40.0F ); credits[i] && y < viddef.height; y += 10, i++ )
                   1743:        {
                   1744:                int j, stringoffset = 0;
                   1745:                int bold = false;
                   1746: 
                   1747:                if ( y <= -8 )
                   1748:                        continue;
                   1749: 
                   1750:                if ( credits[i][0] == '+' )
                   1751:                {
                   1752:                        bold = true;
                   1753:                        stringoffset = 1;
                   1754:                }
                   1755:                else
                   1756:                {
                   1757:                        bold = false;
                   1758:                        stringoffset = 0;
                   1759:                }
                   1760: 
                   1761:                for ( j = 0; credits[i][j+stringoffset]; j++ )
                   1762:                {
                   1763:                        int x;
                   1764: 
                   1765:                        x = ( viddef.width - strlen( credits[i] ) * 8 - stringoffset * 8 ) / 2 + ( j + stringoffset ) * 8;
                   1766: 
                   1767:                        if ( bold )
                   1768:                                re.DrawChar( x, y, credits[i][j+stringoffset] + 128 );
                   1769:                        else
                   1770:                                re.DrawChar( x, y, credits[i][j+stringoffset] );
                   1771:                }
                   1772:        }
                   1773: 
                   1774:        if ( y < 0 )
                   1775:                credits_start_time = cls.realtime;
                   1776: }
                   1777: 
                   1778: const char *M_Credits_Key( int key )
                   1779: {
                   1780:        switch (key)
                   1781:        {
                   1782:        case K_ESCAPE:
1.1.1.2   root     1783:                if (creditsBuffer)
                   1784:                        FS_FreeFile (creditsBuffer);
1.1       root     1785:                M_PopMenu ();
                   1786:                break;
                   1787:        }
                   1788: 
                   1789:        return menu_out_sound;
                   1790: 
                   1791: }
                   1792: 
1.1.1.2   root     1793: extern int Developer_searchpath (int who);
                   1794: 
1.1       root     1795: void M_Menu_Credits_f( void )
                   1796: {
1.1.1.2   root     1797:        int             n;
                   1798:        int             count;
                   1799:        char    *p;
                   1800:        int             isdeveloper = 0;
                   1801: 
                   1802:        creditsBuffer = NULL;
                   1803:        count = FS_LoadFile ("credits", &creditsBuffer);
                   1804:        if (count != -1)
                   1805:        {
                   1806:                p = creditsBuffer;
                   1807:                for (n = 0; n < 255; n++)
                   1808:                {
                   1809:                        creditsIndex[n] = p;
                   1810:                        while (*p != '\r' && *p != '\n')
                   1811:                        {
                   1812:                                p++;
                   1813:                                if (--count == 0)
                   1814:                                        break;
                   1815:                        }
                   1816:                        if (*p == '\r')
                   1817:                        {
                   1818:                                *p++ = 0;
                   1819:                                if (--count == 0)
                   1820:                                        break;
                   1821:                        }
                   1822:                        *p++ = 0;
                   1823:                        if (--count == 0)
                   1824:                                break;
                   1825:                }
                   1826:                creditsIndex[++n] = 0;
                   1827:                credits = creditsIndex;
                   1828:        }
                   1829:        else
                   1830:        {
                   1831:                isdeveloper = Developer_searchpath (1);
                   1832:                
1.1.1.3 ! root     1833:                if (isdeveloper == 1)                   // xatrix
1.1.1.2   root     1834:                        credits = xatcredits;
1.1.1.3 ! root     1835:                else if (isdeveloper == 2)              // ROGUE
        !          1836:                        credits = roguecredits;
1.1.1.2   root     1837:                else
                   1838:                {
                   1839:                        credits = idcredits;    
                   1840:                }
                   1841: 
                   1842:        }
                   1843: 
1.1       root     1844:        credits_start_time = cls.realtime;
                   1845:        M_PushMenu( M_Credits_MenuDraw, M_Credits_Key);
                   1846: }
1.1.1.2   root     1847: 
1.1       root     1848: /*
                   1849: =============================================================================
                   1850: 
                   1851: GAME MENU
                   1852: 
                   1853: =============================================================================
                   1854: */
1.1.1.2   root     1855: 
1.1       root     1856: static int             m_game_cursor;
1.1.1.2   root     1857: 
1.1       root     1858: static menuframework_s s_game_menu;
                   1859: static menuaction_s            s_easy_game_action;
                   1860: static menuaction_s            s_medium_game_action;
                   1861: static menuaction_s            s_hard_game_action;
                   1862: static menuaction_s            s_load_game_action;
                   1863: static menuaction_s            s_save_game_action;
                   1864: static menuaction_s            s_credits_action;
                   1865: static menuseparator_s s_blankline;
1.1.1.2   root     1866: 
1.1       root     1867: static void StartGame( void )
                   1868: {
                   1869:        // disable updates and start the cinematic going
                   1870:        cl.servercount = -1;
                   1871:        M_ForceMenuOff ();
                   1872:        Cvar_SetValue( "deathmatch", 0 );
                   1873:        Cvar_SetValue( "coop", 0 );
1.1.1.3 ! root     1874: 
        !          1875:        Cvar_SetValue( "gamerules", 0 );                //PGM
        !          1876: 
1.1       root     1877:        Cbuf_AddText ("loading ; killserver ; wait ; newgame\n");
                   1878:        cls.key_dest = key_game;
                   1879: }
1.1.1.2   root     1880: 
1.1       root     1881: static void EasyGameFunc( void *data )
                   1882: {
                   1883:        Cvar_ForceSet( "skill", "0" );
                   1884:        StartGame();
                   1885: }
1.1.1.2   root     1886: 
1.1       root     1887: static void MediumGameFunc( void *data )
                   1888: {
                   1889:        Cvar_ForceSet( "skill", "1" );
                   1890:        StartGame();
                   1891: }
1.1.1.2   root     1892: 
1.1       root     1893: static void HardGameFunc( void *data )
                   1894: {
                   1895:        Cvar_ForceSet( "skill", "2" );
                   1896:        StartGame();
                   1897: }
1.1.1.2   root     1898: 
1.1       root     1899: static void LoadGameFunc( void *unused )
                   1900: {
                   1901:        M_Menu_LoadGame_f ();
                   1902: }
1.1.1.2   root     1903: 
1.1       root     1904: static void SaveGameFunc( void *unused )
                   1905: {
                   1906:        M_Menu_SaveGame_f();
                   1907: }
1.1.1.2   root     1908: 
1.1       root     1909: static void CreditsFunc( void *unused )
                   1910: {
                   1911:        M_Menu_Credits_f();
                   1912: }
1.1.1.2   root     1913: 
1.1       root     1914: void Game_MenuInit( void )
                   1915: {
                   1916:        static const char *difficulty_names[] =
                   1917:        {
                   1918:                "easy",
                   1919:                "medium",
                   1920:                "hard",
                   1921:                0
                   1922:        };
1.1.1.2   root     1923: 
1.1       root     1924:        s_game_menu.x = viddef.width * 0.50;
                   1925:        s_game_menu.nitems = 0;
1.1.1.2   root     1926: 
1.1       root     1927:        s_easy_game_action.generic.type = MTYPE_ACTION;
                   1928:        s_easy_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1929:        s_easy_game_action.generic.x            = 0;
                   1930:        s_easy_game_action.generic.y            = 0;
                   1931:        s_easy_game_action.generic.name = "easy";
                   1932:        s_easy_game_action.generic.callback = EasyGameFunc;
1.1.1.2   root     1933: 
1.1       root     1934:        s_medium_game_action.generic.type       = MTYPE_ACTION;
                   1935:        s_medium_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1936:        s_medium_game_action.generic.x          = 0;
                   1937:        s_medium_game_action.generic.y          = 10;
                   1938:        s_medium_game_action.generic.name       = "medium";
                   1939:        s_medium_game_action.generic.callback = MediumGameFunc;
1.1.1.2   root     1940: 
1.1       root     1941:        s_hard_game_action.generic.type = MTYPE_ACTION;
                   1942:        s_hard_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1943:        s_hard_game_action.generic.x            = 0;
                   1944:        s_hard_game_action.generic.y            = 20;
                   1945:        s_hard_game_action.generic.name = "hard";
                   1946:        s_hard_game_action.generic.callback = HardGameFunc;
1.1.1.2   root     1947: 
1.1       root     1948:        s_blankline.generic.type = MTYPE_SEPARATOR;
                   1949: 
                   1950:        s_load_game_action.generic.type = MTYPE_ACTION;
                   1951:        s_load_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1952:        s_load_game_action.generic.x            = 0;
                   1953:        s_load_game_action.generic.y            = 40;
                   1954:        s_load_game_action.generic.name = "load game";
                   1955:        s_load_game_action.generic.callback = LoadGameFunc;
1.1.1.2   root     1956: 
1.1       root     1957:        s_save_game_action.generic.type = MTYPE_ACTION;
                   1958:        s_save_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1959:        s_save_game_action.generic.x            = 0;
                   1960:        s_save_game_action.generic.y            = 50;
                   1961:        s_save_game_action.generic.name = "save game";
                   1962:        s_save_game_action.generic.callback = SaveGameFunc;
                   1963: 
                   1964:        s_credits_action.generic.type   = MTYPE_ACTION;
                   1965:        s_credits_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1966:        s_credits_action.generic.x              = 0;
                   1967:        s_credits_action.generic.y              = 60;
                   1968:        s_credits_action.generic.name   = "credits";
                   1969:        s_credits_action.generic.callback = CreditsFunc;
1.1.1.2   root     1970: 
1.1       root     1971:        Menu_AddItem( &s_game_menu, ( void * ) &s_easy_game_action );
                   1972:        Menu_AddItem( &s_game_menu, ( void * ) &s_medium_game_action );
                   1973:        Menu_AddItem( &s_game_menu, ( void * ) &s_hard_game_action );
                   1974:        Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
                   1975:        Menu_AddItem( &s_game_menu, ( void * ) &s_load_game_action );
                   1976:        Menu_AddItem( &s_game_menu, ( void * ) &s_save_game_action );
                   1977:        Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
                   1978:        Menu_AddItem( &s_game_menu, ( void * ) &s_credits_action );
1.1.1.2   root     1979: 
1.1       root     1980:        Menu_Center( &s_game_menu );
                   1981: }
1.1.1.2   root     1982: 
1.1       root     1983: void Game_MenuDraw( void )
                   1984: {
                   1985:        M_Banner( "m_banner_game" );
                   1986:        Menu_AdjustCursor( &s_game_menu, 1 );
                   1987:        Menu_Draw( &s_game_menu );
                   1988: }
1.1.1.2   root     1989: 
1.1       root     1990: const char *Game_MenuKey( int key )
                   1991: {
                   1992:        return Default_MenuKey( &s_game_menu, key );
                   1993: }
1.1.1.2   root     1994: 
1.1       root     1995: void M_Menu_Game_f (void)
                   1996: {
                   1997:        Game_MenuInit();
                   1998:        M_PushMenu( Game_MenuDraw, Game_MenuKey );
                   1999:        m_game_cursor = 1;
                   2000: }
1.1.1.2   root     2001: 
1.1       root     2002: /*
                   2003: =============================================================================
1.1.1.2   root     2004: 
1.1       root     2005: LOADGAME MENU
1.1.1.2   root     2006: 
1.1       root     2007: =============================================================================
                   2008: */
1.1.1.2   root     2009: 
1.1       root     2010: #define        MAX_SAVEGAMES   15
1.1.1.2   root     2011: 
1.1       root     2012: static menuframework_s s_savegame_menu;
1.1.1.2   root     2013: 
1.1       root     2014: static menuframework_s s_loadgame_menu;
                   2015: static menuaction_s            s_loadgame_actions[MAX_SAVEGAMES];
1.1.1.2   root     2016: 
1.1       root     2017: char           m_savestrings[MAX_SAVEGAMES][32];
                   2018: qboolean       m_savevalid[MAX_SAVEGAMES];
1.1.1.2   root     2019: 
1.1       root     2020: void Create_Savestrings (void)
                   2021: {
                   2022:        int             i;
                   2023:        FILE    *f;
                   2024:        char    name[MAX_OSPATH];
1.1.1.2   root     2025: 
1.1       root     2026:        for (i=0 ; i<MAX_SAVEGAMES ; i++)
                   2027:        {
                   2028:                Com_sprintf (name, sizeof(name), "%s/save/save%i/server.ssv", FS_Gamedir(), i);
                   2029:                f = fopen (name, "rb");
                   2030:                if (!f)
                   2031:                {
                   2032:                        strcpy (m_savestrings[i], "<EMPTY>");
                   2033:                        m_savevalid[i] = false;
                   2034:                }
                   2035:                else
                   2036:                {
                   2037:                        FS_Read (m_savestrings[i], sizeof(m_savestrings[i]), f);
                   2038:                        fclose (f);
                   2039:                        m_savevalid[i] = true;
                   2040:                }
                   2041:        }
                   2042: }
1.1.1.2   root     2043: 
1.1       root     2044: void LoadGameCallback( void *self )
                   2045: {
                   2046:        menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2   root     2047: 
1.1       root     2048:        if ( m_savevalid[ a->generic.localdata[0] ] )
                   2049:                Cbuf_AddText (va("load save%i\n",  a->generic.localdata[0] ) );
                   2050:        M_ForceMenuOff ();
                   2051: }
1.1.1.2   root     2052: 
1.1       root     2053: void LoadGame_MenuInit( void )
                   2054: {
                   2055:        int i;
1.1.1.2   root     2056: 
1.1       root     2057:        s_loadgame_menu.x = viddef.width / 2 - 120;
                   2058:        s_loadgame_menu.y = viddef.height / 2 - 58;
                   2059:        s_loadgame_menu.nitems = 0;
1.1.1.2   root     2060: 
1.1       root     2061:        Create_Savestrings();
1.1.1.2   root     2062: 
1.1       root     2063:        for ( i = 0; i < MAX_SAVEGAMES; i++ )
                   2064:        {
                   2065:                s_loadgame_actions[i].generic.name                      = m_savestrings[i];
                   2066:                s_loadgame_actions[i].generic.flags                     = QMF_LEFT_JUSTIFY;
                   2067:                s_loadgame_actions[i].generic.localdata[0]      = i;
                   2068:                s_loadgame_actions[i].generic.callback          = LoadGameCallback;
1.1.1.2   root     2069: 
1.1       root     2070:                s_loadgame_actions[i].generic.x = 0;
                   2071:                s_loadgame_actions[i].generic.y = ( i ) * 10;
                   2072:                if (i>0)        // separate from autosave
                   2073:                        s_loadgame_actions[i].generic.y += 10;
1.1.1.2   root     2074: 
1.1       root     2075:                s_loadgame_actions[i].generic.type = MTYPE_ACTION;
1.1.1.2   root     2076: 
1.1       root     2077:                Menu_AddItem( &s_loadgame_menu, &s_loadgame_actions[i] );
                   2078:        }
                   2079: }
1.1.1.2   root     2080: 
1.1       root     2081: void LoadGame_MenuDraw( void )
                   2082: {
                   2083:        M_Banner( "m_banner_load_game" );
                   2084: //     Menu_AdjustCursor( &s_loadgame_menu, 1 );
                   2085:        Menu_Draw( &s_loadgame_menu );
                   2086: }
1.1.1.2   root     2087: 
1.1       root     2088: const char *LoadGame_MenuKey( int key )
                   2089: {
                   2090:        if ( key == K_ESCAPE || key == K_ENTER )
                   2091:        {
                   2092:                s_savegame_menu.cursor = s_loadgame_menu.cursor - 1;
                   2093:                if ( s_savegame_menu.cursor < 0 )
                   2094:                        s_savegame_menu.cursor = 0;
                   2095:        }
                   2096:        return Default_MenuKey( &s_loadgame_menu, key );
                   2097: }
1.1.1.2   root     2098: 
1.1       root     2099: void M_Menu_LoadGame_f (void)
                   2100: {
                   2101:        LoadGame_MenuInit();
                   2102:        M_PushMenu( LoadGame_MenuDraw, LoadGame_MenuKey );
                   2103: }
1.1.1.2   root     2104: 
                   2105: 
1.1       root     2106: /*
                   2107: =============================================================================
1.1.1.2   root     2108: 
1.1       root     2109: SAVEGAME MENU
1.1.1.2   root     2110: 
1.1       root     2111: =============================================================================
                   2112: */
                   2113: static menuframework_s s_savegame_menu;
                   2114: static menuaction_s            s_savegame_actions[MAX_SAVEGAMES];
1.1.1.2   root     2115: 
1.1       root     2116: void SaveGameCallback( void *self )
                   2117: {
                   2118:        menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2   root     2119: 
1.1       root     2120:        Cbuf_AddText (va("save save%i\n", a->generic.localdata[0] ));
                   2121:        M_ForceMenuOff ();
                   2122: }
1.1.1.2   root     2123: 
1.1       root     2124: void SaveGame_MenuDraw( void )
                   2125: {
                   2126:        M_Banner( "m_banner_save_game" );
                   2127:        Menu_AdjustCursor( &s_savegame_menu, 1 );
                   2128:        Menu_Draw( &s_savegame_menu );
                   2129: }
1.1.1.2   root     2130: 
1.1       root     2131: void SaveGame_MenuInit( void )
                   2132: {
                   2133:        int i;
1.1.1.2   root     2134: 
1.1       root     2135:        s_savegame_menu.x = viddef.width / 2 - 120;
                   2136:        s_savegame_menu.y = viddef.height / 2 - 58;
                   2137:        s_savegame_menu.nitems = 0;
1.1.1.2   root     2138: 
1.1       root     2139:        Create_Savestrings();
1.1.1.2   root     2140: 
1.1       root     2141:        // don't include the autosave slot
                   2142:        for ( i = 0; i < MAX_SAVEGAMES-1; i++ )
                   2143:        {
                   2144:                s_savegame_actions[i].generic.name = m_savestrings[i+1];
                   2145:                s_savegame_actions[i].generic.localdata[0] = i+1;
                   2146:                s_savegame_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
                   2147:                s_savegame_actions[i].generic.callback = SaveGameCallback;
1.1.1.2   root     2148: 
1.1       root     2149:                s_savegame_actions[i].generic.x = 0;
                   2150:                s_savegame_actions[i].generic.y = ( i ) * 10;
1.1.1.2   root     2151: 
1.1       root     2152:                s_savegame_actions[i].generic.type = MTYPE_ACTION;
1.1.1.2   root     2153: 
1.1       root     2154:                Menu_AddItem( &s_savegame_menu, &s_savegame_actions[i] );
                   2155:        }
                   2156: }
1.1.1.2   root     2157: 
1.1       root     2158: const char *SaveGame_MenuKey( int key )
                   2159: {
                   2160:        if ( key == K_ENTER || key == K_ESCAPE )
                   2161:        {
                   2162:                s_loadgame_menu.cursor = s_savegame_menu.cursor - 1;
                   2163:                if ( s_loadgame_menu.cursor < 0 )
                   2164:                        s_loadgame_menu.cursor = 0;
                   2165:        }
                   2166:        return Default_MenuKey( &s_savegame_menu, key );
                   2167: }
1.1.1.2   root     2168: 
1.1       root     2169: void M_Menu_SaveGame_f (void)
                   2170: {
                   2171:        if (!Com_ServerState())
                   2172:                return;         // not playing a game
1.1.1.2   root     2173: 
1.1       root     2174:        SaveGame_MenuInit();
                   2175:        M_PushMenu( SaveGame_MenuDraw, SaveGame_MenuKey );
                   2176:        Create_Savestrings ();
                   2177: }
1.1.1.2   root     2178: 
                   2179: 
1.1       root     2180: /*
                   2181: =============================================================================
1.1.1.2   root     2182: 
1.1       root     2183: JOIN SERVER MENU
1.1.1.2   root     2184: 
1.1       root     2185: =============================================================================
                   2186: */
                   2187: #define MAX_LOCAL_SERVERS 8
1.1.1.2   root     2188: 
1.1       root     2189: static menuframework_s s_joinserver_menu;
                   2190: static menuseparator_s s_joinserver_server_title;
                   2191: static menuaction_s            s_joinserver_search_action;
                   2192: static menuaction_s            s_joinserver_address_book_action;
                   2193: static menuaction_s            s_joinserver_server_actions[MAX_LOCAL_SERVERS];
                   2194: 
                   2195: int            m_num_servers;
                   2196: #define        NO_SERVER_STRING        "<no server>"
                   2197: 
                   2198: // user readable information
                   2199: static char local_server_names[MAX_LOCAL_SERVERS][80];
                   2200: 
                   2201: // network address
                   2202: static netadr_t local_server_netadr[MAX_LOCAL_SERVERS];
                   2203: 
                   2204: void M_AddToServerList (netadr_t adr, char *info)
                   2205: {
                   2206:        int             i;
                   2207: 
                   2208:        if (m_num_servers == MAX_LOCAL_SERVERS)
                   2209:                return;
                   2210:        while ( *info == ' ' )
                   2211:                info++;
                   2212: 
                   2213:        // ignore if duplicated
                   2214:        for (i=0 ; i<m_num_servers ; i++)
                   2215:                if (!strcmp(info, local_server_names[i]))
                   2216:                        return;
                   2217: 
                   2218:        local_server_netadr[m_num_servers] = adr;
                   2219:        strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1);
                   2220:        m_num_servers++;
                   2221: }
                   2222: 
1.1.1.2   root     2223: 
1.1       root     2224: void JoinServerFunc( void *self )
                   2225: {
                   2226:        char    buffer[128];
                   2227:        int             index;
                   2228: 
                   2229:        index = ( menuaction_s * ) self - s_joinserver_server_actions;
                   2230: 
                   2231:        if ( Q_stricmp( local_server_names[index], NO_SERVER_STRING ) == 0 )
                   2232:                return;
                   2233: 
                   2234:        if (index >= m_num_servers)
                   2235:                return;
                   2236: 
                   2237:        Com_sprintf (buffer, sizeof(buffer), "connect %s\n", NET_AdrToString (local_server_netadr[index]));
                   2238:        Cbuf_AddText (buffer);
                   2239:        M_ForceMenuOff ();
                   2240: }
1.1.1.2   root     2241: 
1.1       root     2242: void AddressBookFunc( void *self )
                   2243: {
                   2244:        M_Menu_AddressBook_f();
                   2245: }
1.1.1.2   root     2246: 
1.1       root     2247: void NullCursorDraw( void *self )
                   2248: {
                   2249: }
                   2250: 
                   2251: void SearchLocalGames( void )
                   2252: {
                   2253:        int             i;
                   2254: 
                   2255:        m_num_servers = 0;
                   2256:        for (i=0 ; i<MAX_LOCAL_SERVERS ; i++)
                   2257:                strcpy (local_server_names[i], NO_SERVER_STRING);
                   2258: 
                   2259:        M_DrawTextBox( 8, 120 - 48, 36, 3 );
                   2260:        M_Print( 16 + 16, 120 - 48 + 8,  "Searching for local servers, this" );
                   2261:        M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
                   2262:        M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
                   2263: 
                   2264:        // the text box won't show up unless we do a buffer swap
                   2265:        re.EndFrame();
                   2266: 
                   2267:        // send out info packets
                   2268:        CL_PingServers_f();
                   2269: }
1.1.1.2   root     2270: 
1.1       root     2271: void SearchLocalGamesFunc( void *self )
                   2272: {
                   2273:        SearchLocalGames();
                   2274: }
1.1.1.2   root     2275: 
1.1       root     2276: void JoinServer_MenuInit( void )
                   2277: {
                   2278:        int i;
1.1.1.2   root     2279: 
1.1       root     2280:        s_joinserver_menu.x = viddef.width * 0.50 - 120;
                   2281:        s_joinserver_menu.nitems = 0;
1.1.1.2   root     2282: 
1.1       root     2283:        s_joinserver_address_book_action.generic.type   = MTYPE_ACTION;
                   2284:        s_joinserver_address_book_action.generic.name   = "address book";
                   2285:        s_joinserver_address_book_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   2286:        s_joinserver_address_book_action.generic.x              = 0;
                   2287:        s_joinserver_address_book_action.generic.y              = 0;
                   2288:        s_joinserver_address_book_action.generic.callback = AddressBookFunc;
1.1.1.2   root     2289: 
1.1       root     2290:        s_joinserver_search_action.generic.type = MTYPE_ACTION;
                   2291:        s_joinserver_search_action.generic.name = "refresh server list";
                   2292:        s_joinserver_search_action.generic.flags        = QMF_LEFT_JUSTIFY;
                   2293:        s_joinserver_search_action.generic.x    = 0;
                   2294:        s_joinserver_search_action.generic.y    = 10;
                   2295:        s_joinserver_search_action.generic.callback = SearchLocalGamesFunc;
                   2296:        s_joinserver_search_action.generic.statusbar = "search for servers";
1.1.1.2   root     2297: 
1.1       root     2298:        s_joinserver_server_title.generic.type = MTYPE_SEPARATOR;
                   2299:        s_joinserver_server_title.generic.name = "connect to...";
                   2300:        s_joinserver_server_title.generic.x    = 80;
                   2301:        s_joinserver_server_title.generic.y        = 30;
1.1.1.2   root     2302: 
1.1       root     2303:        for ( i = 0; i < MAX_LOCAL_SERVERS; i++ )
                   2304:        {
                   2305:                s_joinserver_server_actions[i].generic.type     = MTYPE_ACTION;
                   2306:                strcpy (local_server_names[i], NO_SERVER_STRING);
                   2307:                s_joinserver_server_actions[i].generic.name     = local_server_names[i];
                   2308:                s_joinserver_server_actions[i].generic.flags    = QMF_LEFT_JUSTIFY;
                   2309:                s_joinserver_server_actions[i].generic.x                = 0;
                   2310:                s_joinserver_server_actions[i].generic.y                = 40 + i*10;
                   2311:                s_joinserver_server_actions[i].generic.callback = JoinServerFunc;
                   2312:                s_joinserver_server_actions[i].generic.statusbar = "press ENTER to connect";
                   2313:        }
1.1.1.2   root     2314: 
1.1       root     2315:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_address_book_action );
                   2316:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_title );
                   2317:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_search_action );
1.1.1.2   root     2318: 
1.1       root     2319:        for ( i = 0; i < 8; i++ )
                   2320:                Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_actions[i] );
1.1.1.2   root     2321: 
1.1       root     2322:        Menu_Center( &s_joinserver_menu );
                   2323: 
                   2324:        SearchLocalGames();
                   2325: }
1.1.1.2   root     2326: 
1.1       root     2327: void JoinServer_MenuDraw(void)
                   2328: {
                   2329:        M_Banner( "m_banner_join_server" );
                   2330:        Menu_Draw( &s_joinserver_menu );
                   2331: }
1.1.1.2   root     2332: 
                   2333: 
1.1       root     2334: const char *JoinServer_MenuKey( int key )
                   2335: {
                   2336:        return Default_MenuKey( &s_joinserver_menu, key );
                   2337: }
1.1.1.2   root     2338: 
1.1       root     2339: void M_Menu_JoinServer_f (void)
                   2340: {
                   2341:        JoinServer_MenuInit();
                   2342:        M_PushMenu( JoinServer_MenuDraw, JoinServer_MenuKey );
                   2343: }
                   2344: 
1.1.1.2   root     2345: 
1.1       root     2346: /*
                   2347: =============================================================================
1.1.1.2   root     2348: 
1.1       root     2349: START SERVER MENU
1.1.1.2   root     2350: 
1.1       root     2351: =============================================================================
                   2352: */
                   2353: static menuframework_s s_startserver_menu;
                   2354: static char **mapnames;
                   2355: static int       nummaps;
1.1.1.2   root     2356: 
1.1       root     2357: static menuaction_s    s_startserver_start_action;
                   2358: static menuaction_s    s_startserver_dmoptions_action;
                   2359: static menufield_s     s_timelimit_field;
                   2360: static menufield_s     s_fraglimit_field;
                   2361: static menufield_s     s_maxclients_field;
                   2362: static menufield_s     s_hostname_field;
                   2363: static menulist_s      s_startmap_list;
                   2364: static menulist_s      s_rules_box;
                   2365: 
                   2366: void DMOptionsFunc( void *self )
                   2367: {
                   2368:        if (s_rules_box.curvalue == 1)
                   2369:                return;
                   2370:        M_Menu_DMOptions_f();
                   2371: }
                   2372: 
                   2373: void RulesChangeFunc ( void *self )
                   2374: {
                   2375:        // DM
                   2376:        if (s_rules_box.curvalue == 0)
                   2377:        {
                   2378:                s_maxclients_field.generic.statusbar = NULL;
                   2379:                s_startserver_dmoptions_action.generic.statusbar = NULL;
                   2380:        }
1.1.1.3 ! root     2381:        else if(s_rules_box.curvalue == 1)              // coop                         // PGM
1.1       root     2382:        {
                   2383:                s_maxclients_field.generic.statusbar = "4 maximum for cooperative";
                   2384:                if (atoi(s_maxclients_field.buffer) > 4)
                   2385:                        strcpy( s_maxclients_field.buffer, "4" );
                   2386:                s_startserver_dmoptions_action.generic.statusbar = "N/A for cooperative";
                   2387:        }
1.1.1.3 ! root     2388: //=====
        !          2389: //PGM
        !          2390:        // ROGUE GAMES
        !          2391:        else if(Developer_searchpath(2) == 2)
        !          2392:        {
        !          2393:                if (s_rules_box.curvalue == 2)                  // tag  
        !          2394:                {
        !          2395:                        s_maxclients_field.generic.statusbar = NULL;
        !          2396:                        s_startserver_dmoptions_action.generic.statusbar = NULL;
        !          2397:                }
        !          2398: /*
        !          2399:                else if(s_rules_box.curvalue == 3)              // deathball
        !          2400:                {
        !          2401:                        s_maxclients_field.generic.statusbar = NULL;
        !          2402:                        s_startserver_dmoptions_action.generic.statusbar = NULL;
        !          2403:                }
        !          2404: */
        !          2405:        }
        !          2406: //PGM
        !          2407: //=====
1.1       root     2408: }
1.1.1.2   root     2409: 
1.1       root     2410: void StartServerActionFunc( void *self )
                   2411: {
                   2412:        char    startmap[1024];
                   2413:        int             timelimit;
                   2414:        int             fraglimit;
                   2415:        int             maxclients;
                   2416:        char    *spot;
1.1.1.2   root     2417: 
1.1       root     2418:        strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 );
                   2419: 
                   2420:        maxclients  = atoi( s_maxclients_field.buffer );
                   2421:        timelimit       = atoi( s_timelimit_field.buffer );
                   2422:        fraglimit       = atoi( s_fraglimit_field.buffer );
                   2423: 
                   2424:        Cvar_SetValue( "maxclients", ClampCvar( 0, maxclients, maxclients ) );
                   2425:        Cvar_SetValue ("timelimit", ClampCvar( 0, timelimit, timelimit ) );
                   2426:        Cvar_SetValue ("fraglimit", ClampCvar( 0, fraglimit, fraglimit ) );
                   2427:        Cvar_Set("hostname", s_hostname_field.buffer );
1.1.1.3 ! root     2428: //     Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
        !          2429: //     Cvar_SetValue ("coop", s_rules_box.curvalue );
        !          2430: 
        !          2431: //PGM
        !          2432:        if((s_rules_box.curvalue < 2) || (Developer_searchpath(2) != 2))
        !          2433:        {
        !          2434:                Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
        !          2435:                Cvar_SetValue ("coop", s_rules_box.curvalue );
        !          2436:                Cvar_SetValue ("gamerules", 0 );
        !          2437:        }
        !          2438:        else
        !          2439:        {
        !          2440:                Cvar_SetValue ("deathmatch", 1 );       // deathmatch is always true for rogue games, right?
        !          2441:                Cvar_SetValue ("coop", 0 );                     // FIXME - this might need to depend on which game we're running
        !          2442:                Cvar_SetValue ("gamerules", s_rules_box.curvalue );
        !          2443:        }
        !          2444: //PGM
1.1       root     2445: 
                   2446:        spot = NULL;
1.1.1.3 ! root     2447:        if (s_rules_box.curvalue == 1)          // PGM
1.1       root     2448:        {
1.1.1.2   root     2449:                if(Q_stricmp(startmap, "bunk1") == 0)
                   2450:                        spot = "start";
                   2451:                else if(Q_stricmp(startmap, "mintro") == 0)
                   2452:                        spot = "start";
                   2453:                else if(Q_stricmp(startmap, "fact1") == 0)
                   2454:                        spot = "start";
                   2455:                else if(Q_stricmp(startmap, "power1") == 0)
                   2456:                        spot = "pstart";
                   2457:                else if(Q_stricmp(startmap, "biggun") == 0)
                   2458:                        spot = "bstart";
                   2459:                else if(Q_stricmp(startmap, "hangar1") == 0)
                   2460:                        spot = "unitstart";
                   2461:                else if(Q_stricmp(startmap, "city1") == 0)
                   2462:                        spot = "unitstart";
                   2463:                else if(Q_stricmp(startmap, "boss1") == 0)
1.1.1.3 ! root     2464:                        spot = "bosstart";
1.1       root     2465:        }
                   2466: 
                   2467:        if (spot)
                   2468:        {
                   2469:                if (Com_ServerState())
                   2470:                        Cbuf_AddText ("disconnect\n");
                   2471:                Cbuf_AddText (va("gamemap \"*%s$%s\"\n", startmap, spot));
                   2472:        }
                   2473:        else
                   2474:        {
                   2475:                Cbuf_AddText (va("map %s\n", startmap));
                   2476:        }
                   2477: 
                   2478:        M_ForceMenuOff ();
                   2479: }
                   2480: 
                   2481: void StartServer_MenuInit( void )
                   2482: {
                   2483:        static const char *dm_coop_names[] =
                   2484:        {
                   2485:                "deathmatch",
                   2486:                "cooperative",
                   2487:                0
                   2488:        };
1.1.1.3 ! root     2489: //=======
        !          2490: //PGM
        !          2491:        static const char *dm_coop_names_rogue[] =
        !          2492:        {
        !          2493:                "deathmatch",
        !          2494:                "cooperative",
        !          2495:                "tag",
        !          2496: //             "deathball",
        !          2497:                0
        !          2498:        };
        !          2499: //PGM
        !          2500: //=======
1.1       root     2501:        char *buffer;
                   2502:        char  mapsname[1024];
                   2503:        char *s;
                   2504:        int length;
                   2505:        int i;
                   2506:        FILE *fp;
                   2507: 
                   2508:        /*
                   2509:        ** load the list of map names
                   2510:        */
                   2511:        Com_sprintf( mapsname, sizeof( mapsname ), "%s/maps.lst", FS_Gamedir() );
                   2512:        if ( ( fp = fopen( mapsname, "rb" ) ) == 0 )
                   2513:        {
                   2514:                if ( ( length = FS_LoadFile( "maps.lst", ( void ** ) &buffer ) ) == -1 )
                   2515:                        Com_Error( ERR_DROP, "couldn't find maps.lst\n" );
                   2516:        }
                   2517:        else
                   2518:        {
1.1.1.2   root     2519: #ifdef _WIN32
1.1       root     2520:                length = filelength( fileno( fp  ) );
1.1.1.2   root     2521: #else
                   2522:                fseek(fp, 0, SEEK_END);
                   2523:                length = ftell(fp);
                   2524:                fseek(fp, 0, SEEK_SET);
                   2525: #endif
1.1       root     2526:                buffer = malloc( length );
                   2527:                fread( buffer, length, 1, fp );
                   2528:        }
                   2529: 
                   2530:        s = buffer;
                   2531: 
                   2532:        i = 0;
                   2533:        while ( i < length )
                   2534:        {
                   2535:                if ( s[i] == '\r' )
                   2536:                        nummaps++;
                   2537:                i++;
                   2538:        }
                   2539: 
                   2540:        if ( nummaps == 0 )
                   2541:                Com_Error( ERR_DROP, "no maps in maps.lst\n" );
                   2542: 
                   2543:        mapnames = malloc( sizeof( char * ) * ( nummaps + 1 ) );
                   2544:        memset( mapnames, 0, sizeof( char * ) * ( nummaps + 1 ) );
                   2545: 
                   2546:        s = buffer;
                   2547: 
                   2548:        for ( i = 0; i < nummaps; i++ )
                   2549:        {
                   2550:     char  shortname[MAX_TOKEN_CHARS];
                   2551:     char  longname[MAX_TOKEN_CHARS];
                   2552:                char  scratch[200];
                   2553:                int             j, l;
                   2554: 
                   2555:                strcpy( shortname, COM_Parse( &s ) );
                   2556:                l = strlen(shortname);
                   2557:                for (j=0 ; j<l ; j++)
                   2558:                        shortname[j] = toupper(shortname[j]);
                   2559:                strcpy( longname, COM_Parse( &s ) );
                   2560:                Com_sprintf( scratch, sizeof( scratch ), "%s\n%s", longname, shortname );
                   2561: 
                   2562:                mapnames[i] = malloc( strlen( scratch ) + 1 );
                   2563:                strcpy( mapnames[i], scratch );
                   2564:        }
                   2565:        mapnames[nummaps] = 0;
                   2566: 
                   2567:        if ( fp != 0 )
                   2568:        {
                   2569:                fp = 0;
                   2570:                free( buffer );
                   2571:        }
                   2572:        else
                   2573:        {
                   2574:                FS_FreeFile( buffer );
                   2575:        }
                   2576: 
                   2577:        /*
                   2578:        ** initialize the menu stuff
                   2579:        */
                   2580:        s_startserver_menu.x = viddef.width * 0.50;
                   2581:        s_startserver_menu.nitems = 0;
1.1.1.2   root     2582: 
1.1       root     2583:        s_startmap_list.generic.type = MTYPE_SPINCONTROL;
                   2584:        s_startmap_list.generic.x       = 0;
                   2585:        s_startmap_list.generic.y       = 0;
                   2586:        s_startmap_list.generic.name    = "initial map";
                   2587:        s_startmap_list.itemnames = mapnames;
1.1.1.2   root     2588: 
1.1       root     2589:        s_rules_box.generic.type = MTYPE_SPINCONTROL;
                   2590:        s_rules_box.generic.x   = 0;
                   2591:        s_rules_box.generic.y   = 20;
                   2592:        s_rules_box.generic.name        = "rules";
1.1.1.3 ! root     2593:        
        !          2594: //PGM - rogue games only available with rogue DLL.
        !          2595:        if(Developer_searchpath(2) == 2)
        !          2596:                s_rules_box.itemnames = dm_coop_names_rogue;
        !          2597:        else
        !          2598:                s_rules_box.itemnames = dm_coop_names;
        !          2599: //PGM
        !          2600: 
1.1       root     2601:        if (Cvar_VariableValue("coop"))
                   2602:                s_rules_box.curvalue = 1;
                   2603:        else
                   2604:                s_rules_box.curvalue = 0;
                   2605:        s_rules_box.generic.callback = RulesChangeFunc;
1.1.1.2   root     2606: 
1.1       root     2607:        s_timelimit_field.generic.type = MTYPE_FIELD;
                   2608:        s_timelimit_field.generic.name = "time limit";
                   2609:        s_timelimit_field.generic.flags = QMF_NUMBERSONLY;
                   2610:        s_timelimit_field.generic.x     = 0;
                   2611:        s_timelimit_field.generic.y     = 36;
                   2612:        s_timelimit_field.generic.statusbar = "0 = no limit";
                   2613:        s_timelimit_field.length = 3;
                   2614:        s_timelimit_field.visible_length = 3;
                   2615:        strcpy( s_timelimit_field.buffer, Cvar_VariableString("timelimit") );
1.1.1.2   root     2616: 
1.1       root     2617:        s_fraglimit_field.generic.type = MTYPE_FIELD;
                   2618:        s_fraglimit_field.generic.name = "frag limit";
                   2619:        s_fraglimit_field.generic.flags = QMF_NUMBERSONLY;
                   2620:        s_fraglimit_field.generic.x     = 0;
                   2621:        s_fraglimit_field.generic.y     = 54;
                   2622:        s_fraglimit_field.generic.statusbar = "0 = no limit";
                   2623:        s_fraglimit_field.length = 3;
                   2624:        s_fraglimit_field.visible_length = 3;
                   2625:        strcpy( s_fraglimit_field.buffer, Cvar_VariableString("fraglimit") );
                   2626: 
                   2627:        /*
                   2628:        ** maxclients determines the maximum number of players that can join
                   2629:        ** the game.  If maxclients is only "1" then we should default the menu
                   2630:        ** option to 8 players, otherwise use whatever its current value is. 
                   2631:        ** Clamping will be done when the server is actually started.
                   2632:        */
                   2633:        s_maxclients_field.generic.type = MTYPE_FIELD;
                   2634:        s_maxclients_field.generic.name = "max players";
                   2635:        s_maxclients_field.generic.flags = QMF_NUMBERSONLY;
                   2636:        s_maxclients_field.generic.x    = 0;
                   2637:        s_maxclients_field.generic.y    = 72;
                   2638:        s_maxclients_field.generic.statusbar = NULL;
                   2639:        s_maxclients_field.length = 3;
                   2640:        s_maxclients_field.visible_length = 3;
                   2641:        if ( Cvar_VariableValue( "maxclients" ) == 1 )
                   2642:                strcpy( s_maxclients_field.buffer, "8" );
                   2643:        else 
                   2644:                strcpy( s_maxclients_field.buffer, Cvar_VariableString("maxclients") );
                   2645: 
                   2646:        s_hostname_field.generic.type = MTYPE_FIELD;
                   2647:        s_hostname_field.generic.name = "hostname";
                   2648:        s_hostname_field.generic.flags = 0;
                   2649:        s_hostname_field.generic.x      = 0;
                   2650:        s_hostname_field.generic.y      = 90;
                   2651:        s_hostname_field.generic.statusbar = NULL;
                   2652:        s_hostname_field.length = 12;
                   2653:        s_hostname_field.visible_length = 12;
                   2654:        strcpy( s_hostname_field.buffer, Cvar_VariableString("hostname") );
                   2655: 
                   2656:        s_startserver_dmoptions_action.generic.type = MTYPE_ACTION;
                   2657:        s_startserver_dmoptions_action.generic.name     = " deathmatch flags";
                   2658:        s_startserver_dmoptions_action.generic.flags= QMF_LEFT_JUSTIFY;
                   2659:        s_startserver_dmoptions_action.generic.x        = 24;
                   2660:        s_startserver_dmoptions_action.generic.y        = 108;
                   2661:        s_startserver_dmoptions_action.generic.statusbar = NULL;
                   2662:        s_startserver_dmoptions_action.generic.callback = DMOptionsFunc;
                   2663: 
                   2664:        s_startserver_start_action.generic.type = MTYPE_ACTION;
                   2665:        s_startserver_start_action.generic.name = " begin";
                   2666:        s_startserver_start_action.generic.flags= QMF_LEFT_JUSTIFY;
                   2667:        s_startserver_start_action.generic.x    = 24;
                   2668:        s_startserver_start_action.generic.y    = 128;
                   2669:        s_startserver_start_action.generic.callback = StartServerActionFunc;
                   2670: 
                   2671:        Menu_AddItem( &s_startserver_menu, &s_startmap_list );
                   2672:        Menu_AddItem( &s_startserver_menu, &s_rules_box );
                   2673:        Menu_AddItem( &s_startserver_menu, &s_timelimit_field );
                   2674:        Menu_AddItem( &s_startserver_menu, &s_fraglimit_field );
                   2675:        Menu_AddItem( &s_startserver_menu, &s_maxclients_field );
                   2676:        Menu_AddItem( &s_startserver_menu, &s_hostname_field );
                   2677:        Menu_AddItem( &s_startserver_menu, &s_startserver_dmoptions_action );
                   2678:        Menu_AddItem( &s_startserver_menu, &s_startserver_start_action );
                   2679: 
                   2680:        Menu_Center( &s_startserver_menu );
                   2681: 
                   2682:        // call this now to set proper inital state
                   2683:        RulesChangeFunc ( NULL );
                   2684: }
1.1.1.2   root     2685: 
1.1       root     2686: void StartServer_MenuDraw(void)
                   2687: {
                   2688:        Menu_Draw( &s_startserver_menu );
                   2689: }
1.1.1.2   root     2690: 
1.1       root     2691: const char *StartServer_MenuKey( int key )
                   2692: {
                   2693:        if ( key == K_ESCAPE )
                   2694:        {
                   2695:                if ( mapnames )
                   2696:                {
                   2697:                        int i;
                   2698: 
                   2699:                        for ( i = 0; i < nummaps; i++ )
                   2700:                                free( mapnames[i] );
                   2701:                        free( mapnames );
                   2702:                }
                   2703:                mapnames = 0;
                   2704:                nummaps = 0;
                   2705:        }
1.1.1.2   root     2706: 
1.1       root     2707:        return Default_MenuKey( &s_startserver_menu, key );
                   2708: }
1.1.1.2   root     2709: 
1.1       root     2710: void M_Menu_StartServer_f (void)
                   2711: {
                   2712:        StartServer_MenuInit();
                   2713:        M_PushMenu( StartServer_MenuDraw, StartServer_MenuKey );
                   2714: }
1.1.1.2   root     2715: 
1.1       root     2716: /*
                   2717: =============================================================================
                   2718: 
                   2719: DMOPTIONS BOOK MENU
                   2720: 
                   2721: =============================================================================
                   2722: */
                   2723: static char dmoptions_statusbar[128];
                   2724: 
                   2725: static menuframework_s s_dmoptions_menu;
                   2726: 
                   2727: static menulist_s      s_friendlyfire_box;
                   2728: static menulist_s      s_falls_box;
                   2729: static menulist_s      s_weapons_stay_box;
                   2730: static menulist_s      s_instant_powerups_box;
                   2731: static menulist_s      s_powerups_box;
                   2732: static menulist_s      s_health_box;
                   2733: static menulist_s      s_spawn_farthest_box;
                   2734: static menulist_s      s_teamplay_box;
                   2735: static menulist_s      s_samelevel_box;
                   2736: static menulist_s      s_force_respawn_box;
                   2737: static menulist_s      s_armor_box;
                   2738: static menulist_s      s_allow_exit_box;
                   2739: static menulist_s      s_infinite_ammo_box;
                   2740: static menulist_s      s_fixed_fov_box;
                   2741: static menulist_s      s_quad_drop_box;
                   2742: 
1.1.1.3 ! root     2743: //ROGUE
        !          2744: static menulist_s      s_no_mines_box;
        !          2745: static menulist_s      s_no_nukes_box;
        !          2746: static menulist_s      s_stack_double_box;
        !          2747: static menulist_s      s_no_spheres_box;
        !          2748: //ROGUE
        !          2749: 
1.1       root     2750: static void DMFlagCallback( void *self )
                   2751: {
                   2752:        menulist_s *f = ( menulist_s * ) self;
                   2753:        int flags;
                   2754:        int bit = 0;
                   2755: 
                   2756:        flags = Cvar_VariableValue( "dmflags" );
                   2757: 
                   2758:        if ( f == &s_friendlyfire_box )
                   2759:        {
                   2760:                if ( f->curvalue )
                   2761:                        flags &= ~DF_NO_FRIENDLY_FIRE;
                   2762:                else
                   2763:                        flags |= DF_NO_FRIENDLY_FIRE;
                   2764:                goto setvalue;
                   2765:        }
                   2766:        else if ( f == &s_falls_box )
                   2767:        {
                   2768:                if ( f->curvalue )
                   2769:                        flags &= ~DF_NO_FALLING;
                   2770:                else
                   2771:                        flags |= DF_NO_FALLING;
                   2772:                goto setvalue;
                   2773:        }
                   2774:        else if ( f == &s_weapons_stay_box ) 
                   2775:        {
                   2776:                bit = DF_WEAPONS_STAY;
                   2777:        }
                   2778:        else if ( f == &s_instant_powerups_box )
                   2779:        {
                   2780:                bit = DF_INSTANT_ITEMS;
                   2781:        }
                   2782:        else if ( f == &s_allow_exit_box )
                   2783:        {
                   2784:                bit = DF_ALLOW_EXIT;
                   2785:        }
                   2786:        else if ( f == &s_powerups_box )
                   2787:        {
                   2788:                if ( f->curvalue )
                   2789:                        flags &= ~DF_NO_ITEMS;
                   2790:                else
                   2791:                        flags |= DF_NO_ITEMS;
                   2792:                goto setvalue;
                   2793:        }
                   2794:        else if ( f == &s_health_box )
                   2795:        {
                   2796:                if ( f->curvalue )
                   2797:                        flags &= ~DF_NO_HEALTH;
                   2798:                else
                   2799:                        flags |= DF_NO_HEALTH;
                   2800:                goto setvalue;
                   2801:        }
                   2802:        else if ( f == &s_spawn_farthest_box )
                   2803:        {
                   2804:                bit = DF_SPAWN_FARTHEST;
                   2805:        }
                   2806:        else if ( f == &s_teamplay_box )
                   2807:        {
                   2808:                if ( f->curvalue == 1 )
                   2809:                {
                   2810:                        flags |=  DF_SKINTEAMS;
                   2811:                        flags &= ~DF_MODELTEAMS;
                   2812:                }
                   2813:                else if ( f->curvalue == 2 )
                   2814:                {
                   2815:                        flags |=  DF_MODELTEAMS;
                   2816:                        flags &= ~DF_SKINTEAMS;
                   2817:                }
                   2818:                else
                   2819:                {
                   2820:                        flags &= ~( DF_MODELTEAMS | DF_SKINTEAMS );
                   2821:                }
                   2822: 
                   2823:                goto setvalue;
                   2824:        }
                   2825:        else if ( f == &s_samelevel_box )
                   2826:        {
                   2827:                bit = DF_SAME_LEVEL;
                   2828:        }
                   2829:        else if ( f == &s_force_respawn_box )
                   2830:        {
                   2831:                bit = DF_FORCE_RESPAWN;
                   2832:        }
                   2833:        else if ( f == &s_armor_box )
                   2834:        {
                   2835:                if ( f->curvalue )
                   2836:                        flags &= ~DF_NO_ARMOR;
                   2837:                else
                   2838:                        flags |= DF_NO_ARMOR;
                   2839:                goto setvalue;
                   2840:        }
                   2841:        else if ( f == &s_infinite_ammo_box )
                   2842:        {
                   2843:                bit = DF_INFINITE_AMMO;
                   2844:        }
                   2845:        else if ( f == &s_fixed_fov_box )
                   2846:        {
                   2847:                bit = DF_FIXED_FOV;
                   2848:        }
                   2849:        else if ( f == &s_quad_drop_box )
                   2850:        {
                   2851:                bit = DF_QUAD_DROP;
                   2852:        }
                   2853: 
1.1.1.3 ! root     2854: //=======
        !          2855: //ROGUE
        !          2856:        else if (Developer_searchpath(2) == 2)
        !          2857:        {
        !          2858:                if ( f == &s_no_mines_box)
        !          2859:                {
        !          2860:                        bit = DF_NO_MINES;
        !          2861:                }
        !          2862:                else if ( f == &s_no_nukes_box)
        !          2863:                {
        !          2864:                        bit = DF_NO_NUKES;
        !          2865:                }
        !          2866:                else if ( f == &s_stack_double_box)
        !          2867:                {
        !          2868:                        bit = DF_NO_STACK_DOUBLE;
        !          2869:                }
        !          2870:                else if ( f == &s_no_spheres_box)
        !          2871:                {
        !          2872:                        bit = DF_NO_SPHERES;
        !          2873:                }
        !          2874:        }
        !          2875: //ROGUE
        !          2876: //=======
1.1       root     2877: 
                   2878:        if ( f )
                   2879:        {
                   2880:                if ( f->curvalue == 0 )
                   2881:                        flags &= ~bit;
                   2882:                else
                   2883:                        flags |= bit;
                   2884:        }
                   2885: 
                   2886: setvalue:
                   2887:        Cvar_SetValue ("dmflags", flags);
                   2888: 
                   2889:        Com_sprintf( dmoptions_statusbar, sizeof( dmoptions_statusbar ), "dmflags = %d", flags );
                   2890: 
                   2891: }
                   2892: 
                   2893: void DMOptions_MenuInit( void )
                   2894: {
                   2895:        static const char *yes_no_names[] =
                   2896:        {
                   2897:                "no", "yes", 0
                   2898:        };
                   2899:        static const char *teamplay_names[] = 
                   2900:        {
                   2901:                "disabled", "by skin", "by model", 0
                   2902:        };
                   2903:        int dmflags = Cvar_VariableValue( "dmflags" );
                   2904:        int y = 0;
                   2905: 
                   2906:        s_dmoptions_menu.x = viddef.width * 0.50;
                   2907:        s_dmoptions_menu.nitems = 0;
                   2908: 
                   2909:        s_falls_box.generic.type = MTYPE_SPINCONTROL;
                   2910:        s_falls_box.generic.x   = 0;
                   2911:        s_falls_box.generic.y   = y;
                   2912:        s_falls_box.generic.name        = "falling damage";
                   2913:        s_falls_box.generic.callback = DMFlagCallback;
                   2914:        s_falls_box.itemnames = yes_no_names;
                   2915:        s_falls_box.curvalue = ( dmflags & DF_NO_FALLING ) == 0;
                   2916: 
                   2917:        s_weapons_stay_box.generic.type = MTYPE_SPINCONTROL;
                   2918:        s_weapons_stay_box.generic.x    = 0;
                   2919:        s_weapons_stay_box.generic.y    = y += 10;
                   2920:        s_weapons_stay_box.generic.name = "weapons stay";
                   2921:        s_weapons_stay_box.generic.callback = DMFlagCallback;
                   2922:        s_weapons_stay_box.itemnames = yes_no_names;
                   2923:        s_weapons_stay_box.curvalue = ( dmflags & DF_WEAPONS_STAY ) != 0;
                   2924: 
                   2925:        s_instant_powerups_box.generic.type = MTYPE_SPINCONTROL;
                   2926:        s_instant_powerups_box.generic.x        = 0;
                   2927:        s_instant_powerups_box.generic.y        = y += 10;
                   2928:        s_instant_powerups_box.generic.name     = "instant powerups";
                   2929:        s_instant_powerups_box.generic.callback = DMFlagCallback;
                   2930:        s_instant_powerups_box.itemnames = yes_no_names;
                   2931:        s_instant_powerups_box.curvalue = ( dmflags & DF_INSTANT_ITEMS ) != 0;
                   2932: 
                   2933:        s_powerups_box.generic.type = MTYPE_SPINCONTROL;
                   2934:        s_powerups_box.generic.x        = 0;
                   2935:        s_powerups_box.generic.y        = y += 10;
                   2936:        s_powerups_box.generic.name     = "allow powerups";
                   2937:        s_powerups_box.generic.callback = DMFlagCallback;
                   2938:        s_powerups_box.itemnames = yes_no_names;
                   2939:        s_powerups_box.curvalue = ( dmflags & DF_NO_ITEMS ) == 0;
                   2940: 
                   2941:        s_health_box.generic.type = MTYPE_SPINCONTROL;
                   2942:        s_health_box.generic.x  = 0;
                   2943:        s_health_box.generic.y  = y += 10;
                   2944:        s_health_box.generic.callback = DMFlagCallback;
                   2945:        s_health_box.generic.name       = "allow health";
                   2946:        s_health_box.itemnames = yes_no_names;
                   2947:        s_health_box.curvalue = ( dmflags & DF_NO_HEALTH ) == 0;
                   2948: 
                   2949:        s_armor_box.generic.type = MTYPE_SPINCONTROL;
                   2950:        s_armor_box.generic.x   = 0;
                   2951:        s_armor_box.generic.y   = y += 10;
                   2952:        s_armor_box.generic.name        = "allow armor";
                   2953:        s_armor_box.generic.callback = DMFlagCallback;
                   2954:        s_armor_box.itemnames = yes_no_names;
                   2955:        s_armor_box.curvalue = ( dmflags & DF_NO_ARMOR ) == 0;
                   2956: 
                   2957:        s_spawn_farthest_box.generic.type = MTYPE_SPINCONTROL;
                   2958:        s_spawn_farthest_box.generic.x  = 0;
                   2959:        s_spawn_farthest_box.generic.y  = y += 10;
                   2960:        s_spawn_farthest_box.generic.name       = "spawn farthest";
                   2961:        s_spawn_farthest_box.generic.callback = DMFlagCallback;
                   2962:        s_spawn_farthest_box.itemnames = yes_no_names;
                   2963:        s_spawn_farthest_box.curvalue = ( dmflags & DF_SPAWN_FARTHEST ) != 0;
                   2964: 
                   2965:        s_samelevel_box.generic.type = MTYPE_SPINCONTROL;
                   2966:        s_samelevel_box.generic.x       = 0;
                   2967:        s_samelevel_box.generic.y       = y += 10;
                   2968:        s_samelevel_box.generic.name    = "same map";
                   2969:        s_samelevel_box.generic.callback = DMFlagCallback;
                   2970:        s_samelevel_box.itemnames = yes_no_names;
                   2971:        s_samelevel_box.curvalue = ( dmflags & DF_SAME_LEVEL ) != 0;
                   2972: 
                   2973:        s_force_respawn_box.generic.type = MTYPE_SPINCONTROL;
                   2974:        s_force_respawn_box.generic.x   = 0;
                   2975:        s_force_respawn_box.generic.y   = y += 10;
                   2976:        s_force_respawn_box.generic.name        = "force respawn";
                   2977:        s_force_respawn_box.generic.callback = DMFlagCallback;
                   2978:        s_force_respawn_box.itemnames = yes_no_names;
                   2979:        s_force_respawn_box.curvalue = ( dmflags & DF_FORCE_RESPAWN ) != 0;
                   2980: 
                   2981:        s_teamplay_box.generic.type = MTYPE_SPINCONTROL;
                   2982:        s_teamplay_box.generic.x        = 0;
                   2983:        s_teamplay_box.generic.y        = y += 10;
                   2984:        s_teamplay_box.generic.name     = "teamplay";
                   2985:        s_teamplay_box.generic.callback = DMFlagCallback;
                   2986:        s_teamplay_box.itemnames = teamplay_names;
                   2987: 
                   2988:        s_allow_exit_box.generic.type = MTYPE_SPINCONTROL;
                   2989:        s_allow_exit_box.generic.x      = 0;
                   2990:        s_allow_exit_box.generic.y      = y += 10;
                   2991:        s_allow_exit_box.generic.name   = "allow exit";
                   2992:        s_allow_exit_box.generic.callback = DMFlagCallback;
                   2993:        s_allow_exit_box.itemnames = yes_no_names;
                   2994:        s_allow_exit_box.curvalue = ( dmflags & DF_ALLOW_EXIT ) != 0;
                   2995: 
                   2996:        s_infinite_ammo_box.generic.type = MTYPE_SPINCONTROL;
                   2997:        s_infinite_ammo_box.generic.x   = 0;
                   2998:        s_infinite_ammo_box.generic.y   = y += 10;
                   2999:        s_infinite_ammo_box.generic.name        = "infinite ammo";
                   3000:        s_infinite_ammo_box.generic.callback = DMFlagCallback;
                   3001:        s_infinite_ammo_box.itemnames = yes_no_names;
                   3002:        s_infinite_ammo_box.curvalue = ( dmflags & DF_INFINITE_AMMO ) != 0;
                   3003: 
                   3004:        s_fixed_fov_box.generic.type = MTYPE_SPINCONTROL;
                   3005:        s_fixed_fov_box.generic.x       = 0;
                   3006:        s_fixed_fov_box.generic.y       = y += 10;
                   3007:        s_fixed_fov_box.generic.name    = "fixed FOV";
                   3008:        s_fixed_fov_box.generic.callback = DMFlagCallback;
                   3009:        s_fixed_fov_box.itemnames = yes_no_names;
                   3010:        s_fixed_fov_box.curvalue = ( dmflags & DF_FIXED_FOV ) != 0;
                   3011: 
                   3012:        s_quad_drop_box.generic.type = MTYPE_SPINCONTROL;
                   3013:        s_quad_drop_box.generic.x       = 0;
                   3014:        s_quad_drop_box.generic.y       = y += 10;
                   3015:        s_quad_drop_box.generic.name    = "quad drop";
                   3016:        s_quad_drop_box.generic.callback = DMFlagCallback;
                   3017:        s_quad_drop_box.itemnames = yes_no_names;
                   3018:        s_quad_drop_box.curvalue = ( dmflags & DF_QUAD_DROP ) != 0;
                   3019: 
                   3020:        s_friendlyfire_box.generic.type = MTYPE_SPINCONTROL;
                   3021:        s_friendlyfire_box.generic.x    = 0;
                   3022:        s_friendlyfire_box.generic.y    = y += 10;
                   3023:        s_friendlyfire_box.generic.name = "friendly fire";
                   3024:        s_friendlyfire_box.generic.callback = DMFlagCallback;
                   3025:        s_friendlyfire_box.itemnames = yes_no_names;
                   3026:        s_friendlyfire_box.curvalue = ( dmflags & DF_NO_FRIENDLY_FIRE ) == 0;
                   3027: 
1.1.1.3 ! root     3028: //============
        !          3029: //ROGUE
        !          3030:        if(Developer_searchpath(2) == 2)
        !          3031:        {
        !          3032:                s_no_mines_box.generic.type = MTYPE_SPINCONTROL;
        !          3033:                s_no_mines_box.generic.x        = 0;
        !          3034:                s_no_mines_box.generic.y        = y += 10;
        !          3035:                s_no_mines_box.generic.name     = "remove mines";
        !          3036:                s_no_mines_box.generic.callback = DMFlagCallback;
        !          3037:                s_no_mines_box.itemnames = yes_no_names;
        !          3038:                s_no_mines_box.curvalue = ( dmflags & DF_NO_MINES ) != 0;
        !          3039: 
        !          3040:                s_no_nukes_box.generic.type = MTYPE_SPINCONTROL;
        !          3041:                s_no_nukes_box.generic.x        = 0;
        !          3042:                s_no_nukes_box.generic.y        = y += 10;
        !          3043:                s_no_nukes_box.generic.name     = "remove nukes";
        !          3044:                s_no_nukes_box.generic.callback = DMFlagCallback;
        !          3045:                s_no_nukes_box.itemnames = yes_no_names;
        !          3046:                s_no_nukes_box.curvalue = ( dmflags & DF_NO_NUKES ) != 0;
        !          3047: 
        !          3048:                s_stack_double_box.generic.type = MTYPE_SPINCONTROL;
        !          3049:                s_stack_double_box.generic.x    = 0;
        !          3050:                s_stack_double_box.generic.y    = y += 10;
        !          3051:                s_stack_double_box.generic.name = "2x/4x stacking off";
        !          3052:                s_stack_double_box.generic.callback = DMFlagCallback;
        !          3053:                s_stack_double_box.itemnames = yes_no_names;
        !          3054:                s_stack_double_box.curvalue = ( dmflags & DF_NO_STACK_DOUBLE ) != 0;
        !          3055: 
        !          3056:                s_no_spheres_box.generic.type = MTYPE_SPINCONTROL;
        !          3057:                s_no_spheres_box.generic.x      = 0;
        !          3058:                s_no_spheres_box.generic.y      = y += 10;
        !          3059:                s_no_spheres_box.generic.name   = "remove spheres";
        !          3060:                s_no_spheres_box.generic.callback = DMFlagCallback;
        !          3061:                s_no_spheres_box.itemnames = yes_no_names;
        !          3062:                s_no_spheres_box.curvalue = ( dmflags & DF_NO_SPHERES ) != 0;
        !          3063: 
        !          3064:        }
        !          3065: //ROGUE
        !          3066: //============
        !          3067: 
1.1       root     3068:        Menu_AddItem( &s_dmoptions_menu, &s_falls_box );
                   3069:        Menu_AddItem( &s_dmoptions_menu, &s_weapons_stay_box );
                   3070:        Menu_AddItem( &s_dmoptions_menu, &s_instant_powerups_box );
                   3071:        Menu_AddItem( &s_dmoptions_menu, &s_powerups_box );
                   3072:        Menu_AddItem( &s_dmoptions_menu, &s_health_box );
                   3073:        Menu_AddItem( &s_dmoptions_menu, &s_armor_box );
                   3074:        Menu_AddItem( &s_dmoptions_menu, &s_spawn_farthest_box );
                   3075:        Menu_AddItem( &s_dmoptions_menu, &s_samelevel_box );
                   3076:        Menu_AddItem( &s_dmoptions_menu, &s_force_respawn_box );
                   3077:        Menu_AddItem( &s_dmoptions_menu, &s_teamplay_box );
                   3078:        Menu_AddItem( &s_dmoptions_menu, &s_allow_exit_box );
                   3079:        Menu_AddItem( &s_dmoptions_menu, &s_infinite_ammo_box );
                   3080:        Menu_AddItem( &s_dmoptions_menu, &s_fixed_fov_box );
                   3081:        Menu_AddItem( &s_dmoptions_menu, &s_quad_drop_box );
                   3082:        Menu_AddItem( &s_dmoptions_menu, &s_friendlyfire_box );
                   3083: 
1.1.1.3 ! root     3084: //=======
        !          3085: //ROGUE
        !          3086:        if(Developer_searchpath(2) == 2)
        !          3087:        {
        !          3088:                Menu_AddItem( &s_dmoptions_menu, &s_no_mines_box );
        !          3089:                Menu_AddItem( &s_dmoptions_menu, &s_no_nukes_box );
        !          3090:                Menu_AddItem( &s_dmoptions_menu, &s_stack_double_box );
        !          3091:                Menu_AddItem( &s_dmoptions_menu, &s_no_spheres_box );
        !          3092:        }
        !          3093: //ROGUE
        !          3094: //=======
        !          3095: 
1.1       root     3096:        Menu_Center( &s_dmoptions_menu );
                   3097: 
                   3098:        // set the original dmflags statusbar
                   3099:        DMFlagCallback( 0 );
                   3100:        Menu_SetStatusBar( &s_dmoptions_menu, dmoptions_statusbar );
                   3101: }
                   3102: 
                   3103: void DMOptions_MenuDraw(void)
                   3104: {
                   3105:        Menu_Draw( &s_dmoptions_menu );
                   3106: }
                   3107: 
                   3108: const char *DMOptions_MenuKey( int key )
                   3109: {
                   3110:        return Default_MenuKey( &s_dmoptions_menu, key );
                   3111: }
                   3112: 
                   3113: void M_Menu_DMOptions_f (void)
                   3114: {
                   3115:        DMOptions_MenuInit();
                   3116:        M_PushMenu( DMOptions_MenuDraw, DMOptions_MenuKey );
                   3117: }
                   3118: 
                   3119: /*
                   3120: =============================================================================
1.1.1.2   root     3121: 
                   3122: DOWNLOADOPTIONS BOOK MENU
                   3123: 
                   3124: =============================================================================
                   3125: */
                   3126: static menuframework_s s_downloadoptions_menu;
                   3127: 
                   3128: static menuseparator_s s_download_title;
                   3129: static menulist_s      s_allow_download_box;
                   3130: static menulist_s      s_allow_download_maps_box;
                   3131: static menulist_s      s_allow_download_models_box;
                   3132: static menulist_s      s_allow_download_players_box;
                   3133: static menulist_s      s_allow_download_sounds_box;
                   3134: 
                   3135: static void DownloadCallback( void *self )
                   3136: {
                   3137:        menulist_s *f = ( menulist_s * ) self;
                   3138: 
                   3139:        if (f == &s_allow_download_box)
                   3140:        {
                   3141:                Cvar_SetValue("allow_download", f->curvalue);
                   3142:        }
                   3143: 
                   3144:        else if (f == &s_allow_download_maps_box)
                   3145:        {
                   3146:                Cvar_SetValue("allow_download_maps", f->curvalue);
                   3147:        }
                   3148: 
                   3149:        else if (f == &s_allow_download_models_box)
                   3150:        {
                   3151:                Cvar_SetValue("allow_download_models", f->curvalue);
                   3152:        }
                   3153: 
                   3154:        else if (f == &s_allow_download_players_box)
                   3155:        {
                   3156:                Cvar_SetValue("allow_download_players", f->curvalue);
                   3157:        }
                   3158: 
                   3159:        else if (f == &s_allow_download_sounds_box)
                   3160:        {
                   3161:                Cvar_SetValue("allow_download_sounds", f->curvalue);
                   3162:        }
                   3163: }
                   3164: 
                   3165: void DownloadOptions_MenuInit( void )
                   3166: {
                   3167:        static const char *yes_no_names[] =
                   3168:        {
                   3169:                "no", "yes", 0
                   3170:        };
                   3171:        int y = 0;
                   3172: 
                   3173:        s_downloadoptions_menu.x = viddef.width * 0.50;
                   3174:        s_downloadoptions_menu.nitems = 0;
                   3175: 
                   3176:        s_download_title.generic.type = MTYPE_SEPARATOR;
                   3177:        s_download_title.generic.name = "Download Options";
                   3178:        s_download_title.generic.x    = 48;
                   3179:        s_download_title.generic.y       = y;
                   3180: 
                   3181:        s_allow_download_box.generic.type = MTYPE_SPINCONTROL;
                   3182:        s_allow_download_box.generic.x  = 0;
                   3183:        s_allow_download_box.generic.y  = y += 20;
                   3184:        s_allow_download_box.generic.name       = "allow downloading";
                   3185:        s_allow_download_box.generic.callback = DownloadCallback;
                   3186:        s_allow_download_box.itemnames = yes_no_names;
                   3187:        s_allow_download_box.curvalue = (Cvar_VariableValue("allow_download") != 0);
                   3188: 
                   3189:        s_allow_download_maps_box.generic.type = MTYPE_SPINCONTROL;
                   3190:        s_allow_download_maps_box.generic.x     = 0;
                   3191:        s_allow_download_maps_box.generic.y     = y += 20;
                   3192:        s_allow_download_maps_box.generic.name  = "maps";
                   3193:        s_allow_download_maps_box.generic.callback = DownloadCallback;
                   3194:        s_allow_download_maps_box.itemnames = yes_no_names;
                   3195:        s_allow_download_maps_box.curvalue = (Cvar_VariableValue("allow_download_maps") != 0);
                   3196: 
                   3197:        s_allow_download_players_box.generic.type = MTYPE_SPINCONTROL;
                   3198:        s_allow_download_players_box.generic.x  = 0;
                   3199:        s_allow_download_players_box.generic.y  = y += 10;
                   3200:        s_allow_download_players_box.generic.name       = "player models/skins";
                   3201:        s_allow_download_players_box.generic.callback = DownloadCallback;
                   3202:        s_allow_download_players_box.itemnames = yes_no_names;
                   3203:        s_allow_download_players_box.curvalue = (Cvar_VariableValue("allow_download_players") != 0);
                   3204: 
                   3205:        s_allow_download_models_box.generic.type = MTYPE_SPINCONTROL;
                   3206:        s_allow_download_models_box.generic.x   = 0;
                   3207:        s_allow_download_models_box.generic.y   = y += 10;
                   3208:        s_allow_download_models_box.generic.name        = "models";
                   3209:        s_allow_download_models_box.generic.callback = DownloadCallback;
                   3210:        s_allow_download_models_box.itemnames = yes_no_names;
                   3211:        s_allow_download_models_box.curvalue = (Cvar_VariableValue("allow_download_models") != 0);
                   3212: 
                   3213:        s_allow_download_sounds_box.generic.type = MTYPE_SPINCONTROL;
                   3214:        s_allow_download_sounds_box.generic.x   = 0;
                   3215:        s_allow_download_sounds_box.generic.y   = y += 10;
                   3216:        s_allow_download_sounds_box.generic.name        = "sounds";
                   3217:        s_allow_download_sounds_box.generic.callback = DownloadCallback;
                   3218:        s_allow_download_sounds_box.itemnames = yes_no_names;
                   3219:        s_allow_download_sounds_box.curvalue = (Cvar_VariableValue("allow_download_sounds") != 0);
                   3220: 
                   3221:        Menu_AddItem( &s_downloadoptions_menu, &s_download_title );
                   3222:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_box );
                   3223:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_maps_box );
                   3224:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_players_box );
                   3225:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_models_box );
                   3226:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_sounds_box );
                   3227: 
                   3228:        Menu_Center( &s_downloadoptions_menu );
                   3229: 
                   3230:        // skip over title
                   3231:        if (s_downloadoptions_menu.cursor == 0)
                   3232:                s_downloadoptions_menu.cursor = 1;
                   3233: }
                   3234: 
                   3235: void DownloadOptions_MenuDraw(void)
                   3236: {
                   3237:        Menu_Draw( &s_downloadoptions_menu );
                   3238: }
                   3239: 
                   3240: const char *DownloadOptions_MenuKey( int key )
                   3241: {
                   3242:        return Default_MenuKey( &s_downloadoptions_menu, key );
                   3243: }
                   3244: 
                   3245: void M_Menu_DownloadOptions_f (void)
                   3246: {
                   3247:        DownloadOptions_MenuInit();
                   3248:        M_PushMenu( DownloadOptions_MenuDraw, DownloadOptions_MenuKey );
                   3249: }
                   3250: /*
                   3251: =============================================================================
                   3252: 
1.1       root     3253: ADDRESS BOOK MENU
1.1.1.2   root     3254: 
1.1       root     3255: =============================================================================
                   3256: */
                   3257: #define NUM_ADDRESSBOOK_ENTRIES 9
1.1.1.2   root     3258: 
1.1       root     3259: static menuframework_s s_addressbook_menu;
                   3260: static menufield_s             s_addressbook_fields[NUM_ADDRESSBOOK_ENTRIES];
1.1.1.2   root     3261: 
1.1       root     3262: void AddressBook_MenuInit( void )
                   3263: {
                   3264:        int i;
1.1.1.2   root     3265: 
1.1       root     3266:        s_addressbook_menu.x = viddef.width / 2 - 142;
                   3267:        s_addressbook_menu.y = viddef.height / 2 - 58;
                   3268:        s_addressbook_menu.nitems = 0;
1.1.1.2   root     3269: 
1.1       root     3270:        for ( i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++ )
                   3271:        {
                   3272:                cvar_t *adr;
                   3273:                char buffer[20];
                   3274: 
                   3275:                Com_sprintf( buffer, sizeof( buffer ), "adr%d", i );
                   3276: 
                   3277:                adr = Cvar_Get( buffer, "", CVAR_ARCHIVE );
1.1.1.2   root     3278: 
1.1       root     3279:                s_addressbook_fields[i].generic.type = MTYPE_FIELD;
                   3280:                s_addressbook_fields[i].generic.name = 0;
                   3281:                s_addressbook_fields[i].generic.callback = 0;
                   3282:                s_addressbook_fields[i].generic.x               = 0;
                   3283:                s_addressbook_fields[i].generic.y               = i * 18 + 0;
                   3284:                s_addressbook_fields[i].generic.localdata[0] = i;
                   3285:                s_addressbook_fields[i].cursor                  = 0;
                   3286:                s_addressbook_fields[i].length                  = 60;
                   3287:                s_addressbook_fields[i].visible_length  = 30;
                   3288: 
                   3289:                strcpy( s_addressbook_fields[i].buffer, adr->string );
1.1.1.2   root     3290: 
1.1       root     3291:                Menu_AddItem( &s_addressbook_menu, &s_addressbook_fields[i] );
                   3292:        }
                   3293: }
1.1.1.2   root     3294: 
1.1       root     3295: const char *AddressBook_MenuKey( int key )
                   3296: {
                   3297:        if ( key == K_ESCAPE )
                   3298:        {
                   3299:                int index;
                   3300:                char buffer[20];
                   3301: 
                   3302:                for ( index = 0; index < NUM_ADDRESSBOOK_ENTRIES; index++ )
                   3303:                {
                   3304:                        Com_sprintf( buffer, sizeof( buffer ), "adr%d", index );
                   3305:                        Cvar_Set( buffer, s_addressbook_fields[index].buffer );
                   3306:                }
                   3307:        }
                   3308:        return Default_MenuKey( &s_addressbook_menu, key );
                   3309: }
1.1.1.2   root     3310: 
1.1       root     3311: void AddressBook_MenuDraw(void)
                   3312: {
                   3313:        M_Banner( "m_banner_addressbook" );
                   3314:        Menu_Draw( &s_addressbook_menu );
                   3315: }
1.1.1.2   root     3316: 
1.1       root     3317: void M_Menu_AddressBook_f(void)
                   3318: {
                   3319:        AddressBook_MenuInit();
                   3320:        M_PushMenu( AddressBook_MenuDraw, AddressBook_MenuKey );
                   3321: }
1.1.1.2   root     3322: 
1.1       root     3323: /*
                   3324: =============================================================================
1.1.1.2   root     3325: 
1.1       root     3326: PLAYER CONFIG MENU
1.1.1.2   root     3327: 
1.1       root     3328: =============================================================================
                   3329: */
                   3330: static menuframework_s s_player_config_menu;
                   3331: static menufield_s             s_player_name_field;
                   3332: static menulist_s              s_player_model_box;
                   3333: static menulist_s              s_player_skin_box;
                   3334: static menulist_s              s_player_handedness_box;
1.1.1.2   root     3335: static menulist_s              s_player_rate_box;
1.1       root     3336: static menuseparator_s s_player_skin_title;
                   3337: static menuseparator_s s_player_model_title;
                   3338: static menuseparator_s s_player_hand_title;
1.1.1.2   root     3339: static menuseparator_s s_player_rate_title;
                   3340: static menuaction_s            s_player_download_action;
1.1       root     3341: 
                   3342: #define MAX_DISPLAYNAME 16
                   3343: #define MAX_PLAYERMODELS 1024
                   3344: 
                   3345: typedef struct
                   3346: {
                   3347:        int             nskins;
                   3348:        char    **skindisplaynames;
                   3349:        char    displayname[MAX_DISPLAYNAME];
                   3350:        char    directory[MAX_QPATH];
                   3351: } playermodelinfo_s;
                   3352: 
                   3353: static playermodelinfo_s s_pmi[MAX_PLAYERMODELS];
                   3354: static char *s_pmnames[MAX_PLAYERMODELS];
                   3355: static int s_numplayermodels;
                   3356: 
1.1.1.2   root     3357: static int rate_tbl[] = { 2500, 3200, 5000, 10000, 25000, 0 };
                   3358: static const char *rate_names[] = { "28.8 Modem", "33.6 Modem", "Single ISDN",
                   3359:        "Dual ISDN/Cable", "T1/LAN", "User defined", 0 };
                   3360: 
                   3361: void DownloadOptionsFunc( void *self )
                   3362: {
                   3363:        M_Menu_DownloadOptions_f();
                   3364: }
                   3365: 
1.1       root     3366: static void HandednessCallback( void *unused )
                   3367: {
                   3368:        Cvar_SetValue( "hand", s_player_handedness_box.curvalue );
                   3369: }
                   3370: 
1.1.1.2   root     3371: static void RateCallback( void *unused )
                   3372: {
                   3373:        if (s_player_rate_box.curvalue != sizeof(rate_tbl) / sizeof(*rate_tbl) - 1)
                   3374:                Cvar_SetValue( "rate", rate_tbl[s_player_rate_box.curvalue] );
                   3375: }
                   3376: 
1.1       root     3377: static void ModelCallback( void *unused )
                   3378: {
                   3379:        s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames;
                   3380:        s_player_skin_box.curvalue = 0;
                   3381: }
                   3382: 
                   3383: static void FreeFileList( char **list, int n )
                   3384: {
                   3385:        int i;
                   3386: 
                   3387:        for ( i = 0; i < n; i++ )
                   3388:        {
                   3389:                if ( list[i] )
                   3390:                {
                   3391:                        free( list[i] );
                   3392:                        list[i] = 0;
                   3393:                }
                   3394:        }
                   3395:        free( list );
                   3396: }
                   3397: 
                   3398: static qboolean IconOfSkinExists( char *skin, char **pcxfiles, int npcxfiles )
                   3399: {
                   3400:        int i;
                   3401:        char scratch[1024];
                   3402: 
                   3403:        strcpy( scratch, skin );
                   3404:        *strrchr( scratch, '.' ) = 0;
                   3405:        strcat( scratch, "_i.pcx" );
                   3406: 
                   3407:        for ( i = 0; i < npcxfiles; i++ )
                   3408:        {
                   3409:                if ( strcmp( pcxfiles[i], scratch ) == 0 )
                   3410:                        return true;
                   3411:        }
                   3412: 
                   3413:        return false;
                   3414: }
                   3415: 
                   3416: static qboolean PlayerConfig_ScanDirectories( void )
                   3417: {
                   3418:        char findname[1024];
                   3419:        char scratch[1024];
                   3420:        int ndirs = 0, npms = 0;
                   3421:        char **dirnames;
                   3422:        char *path = NULL;
                   3423:        int i;
                   3424: 
                   3425:        extern char **FS_ListFiles( char *, int *, unsigned, unsigned );
                   3426: 
                   3427:        s_numplayermodels = 0;
                   3428: 
                   3429:        /*
                   3430:        ** get a list of directories
                   3431:        */
                   3432:        do 
                   3433:        {
                   3434:                path = FS_NextPath( path );
                   3435:                Com_sprintf( findname, sizeof(findname), "%s/players/*.*", path );
                   3436: 
                   3437:                if ( ( dirnames = FS_ListFiles( findname, &ndirs, SFF_SUBDIR, 0 ) ) != 0 )
                   3438:                        break;
                   3439:        } while ( path );
                   3440: 
                   3441:        if ( !dirnames )
                   3442:                return false;
                   3443: 
                   3444:        /*
                   3445:        ** go through the subdirectories
                   3446:        */
                   3447:        npms = ndirs;
                   3448:        if ( npms > MAX_PLAYERMODELS )
                   3449:                npms = MAX_PLAYERMODELS;
                   3450: 
                   3451:        for ( i = 0; i < npms; i++ )
                   3452:        {
                   3453:                int k, s;
                   3454:                char *a, *b, *c;
                   3455:                char **pcxnames;
                   3456:                char **skinnames;
                   3457:                int npcxfiles;
                   3458:                int nskins = 0;
                   3459: 
                   3460:                if ( dirnames[i] == 0 )
                   3461:                        continue;
                   3462: 
                   3463:                // verify the existence of tris.md2
                   3464:                strcpy( scratch, dirnames[i] );
                   3465:                strcat( scratch, "/tris.md2" );
                   3466:                if ( !Sys_FindFirst( scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM ) )
                   3467:                {
                   3468:                        free( dirnames[i] );
                   3469:                        dirnames[i] = 0;
                   3470:                        Sys_FindClose();
                   3471:                        continue;
                   3472:                }
                   3473:                Sys_FindClose();
                   3474: 
                   3475:                // verify the existence of at least one pcx skin
                   3476:                strcpy( scratch, dirnames[i] );
                   3477:                strcat( scratch, "/*.pcx" );
                   3478:                pcxnames = FS_ListFiles( scratch, &npcxfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM );
                   3479: 
                   3480:                if ( !pcxnames )
                   3481:                {
                   3482:                        free( dirnames[i] );
                   3483:                        dirnames[i] = 0;
                   3484:                        continue;
                   3485:                }
                   3486: 
                   3487:                // count valid skins, which consist of a skin with a matching "_i" icon
                   3488:                for ( k = 0; k < npcxfiles-1; k++ )
                   3489:                {
                   3490:                        if ( !strstr( pcxnames[k], "_i.pcx" ) )
                   3491:                        {
                   3492:                                if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
                   3493:                                {
                   3494:                                        nskins++;
                   3495:                                }
                   3496:                        }
                   3497:                }
                   3498:                if ( !nskins )
                   3499:                        continue;
                   3500: 
                   3501:                skinnames = malloc( sizeof( char * ) * ( nskins + 1 ) );
                   3502:                memset( skinnames, 0, sizeof( char * ) * ( nskins + 1 ) );
                   3503: 
                   3504:                // copy the valid skins
                   3505:                for ( s = 0, k = 0; k < npcxfiles-1; k++ )
                   3506:                {
                   3507:                        char *a, *b, *c;
                   3508: 
                   3509:                        if ( !strstr( pcxnames[k], "_i.pcx" ) )
                   3510:                        {
                   3511:                                if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
                   3512:                                {
                   3513:                                        a = strrchr( pcxnames[k], '/' );
                   3514:                                        b = strrchr( pcxnames[k], '\\' );
                   3515: 
                   3516:                                        if ( a > b )
                   3517:                                                c = a;
                   3518:                                        else
                   3519:                                                c = b;
                   3520: 
                   3521:                                        strcpy( scratch, c + 1 );
                   3522: 
                   3523:                                        if ( strrchr( scratch, '.' ) )
                   3524:                                                *strrchr( scratch, '.' ) = 0;
                   3525: 
                   3526:                                        skinnames[s] = strdup( scratch );
                   3527:                                        s++;
                   3528:                                }
                   3529:                        }
                   3530:                }
                   3531: 
                   3532:                // at this point we have a valid player model
                   3533:                s_pmi[s_numplayermodels].nskins = nskins;
                   3534:                s_pmi[s_numplayermodels].skindisplaynames = skinnames;
                   3535: 
                   3536:                // make short name for the model
                   3537:                a = strrchr( dirnames[i], '/' );
                   3538:                b = strrchr( dirnames[i], '\\' );
                   3539: 
                   3540:                if ( a > b )
                   3541:                        c = a;
                   3542:                else
                   3543:                        c = b;
                   3544: 
                   3545:                strncpy( s_pmi[s_numplayermodels].displayname, c + 1, MAX_DISPLAYNAME-1 );
                   3546:                strcpy( s_pmi[s_numplayermodels].directory, c + 1 );
                   3547: 
                   3548:                FreeFileList( pcxnames, npcxfiles );
                   3549: 
                   3550:                s_numplayermodels++;
                   3551:        }
                   3552:        if ( dirnames )
                   3553:                FreeFileList( dirnames, ndirs );
                   3554: }
                   3555: 
                   3556: static int pmicmpfnc( const void *_a, const void *_b )
                   3557: {
                   3558:        const playermodelinfo_s *a = ( const playermodelinfo_s * ) _a;
                   3559:        const playermodelinfo_s *b = ( const playermodelinfo_s * ) _b;
                   3560: 
                   3561:        /*
                   3562:        ** sort by male, female, then alphabetical
                   3563:        */
                   3564:        if ( strcmp( a->directory, "male" ) == 0 )
                   3565:                return -1;
                   3566:        else if ( strcmp( b->directory, "male" ) == 0 )
                   3567:                return 1;
                   3568: 
                   3569:        if ( strcmp( a->directory, "female" ) == 0 )
                   3570:                return -1;
                   3571:        else if ( strcmp( b->directory, "female" ) == 0 )
                   3572:                return 1;
                   3573: 
                   3574:        return strcmp( a->directory, b->directory );
                   3575: }
                   3576: 
1.1.1.2   root     3577: 
                   3578: qboolean PlayerConfig_MenuInit( void )
1.1       root     3579: {
                   3580:        extern cvar_t *name;
                   3581:        extern cvar_t *team;
                   3582:        extern cvar_t *skin;
                   3583:        char currentdirectory[1024];
                   3584:        char currentskin[1024];
                   3585:        int i = 0;
                   3586: 
                   3587:        int currentdirectoryindex = 0;
                   3588:        int currentskinindex = 0;
                   3589: 
                   3590:        cvar_t *hand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
                   3591: 
                   3592:        static const char *handedness[] = { "right", "left", "center", 0 };
                   3593: 
                   3594:        PlayerConfig_ScanDirectories();
                   3595: 
1.1.1.2   root     3596:        if (s_numplayermodels == 0)
                   3597:                return false;
                   3598: 
1.1       root     3599:        if ( hand->value < 0 || hand->value > 2 )
                   3600:                Cvar_SetValue( "hand", 0 );
                   3601: 
                   3602:        strcpy( currentdirectory, skin->string );
                   3603: 
                   3604:        if ( strchr( currentdirectory, '/' ) )
                   3605:        {
                   3606:                strcpy( currentskin, strchr( currentdirectory, '/' ) + 1 );
                   3607:                *strchr( currentdirectory, '/' ) = 0;
                   3608:        }
                   3609:        else if ( strchr( currentdirectory, '\\' ) )
                   3610:        {
                   3611:                strcpy( currentskin, strchr( currentdirectory, '\\' ) + 1 );
                   3612:                *strchr( currentdirectory, '\\' ) = 0;
                   3613:        }
                   3614:        else
                   3615:        {
                   3616:                strcpy( currentdirectory, "male" );
                   3617:                strcpy( currentskin, "grunt" );
                   3618:        }
                   3619: 
                   3620:        qsort( s_pmi, s_numplayermodels, sizeof( s_pmi[0] ), pmicmpfnc );
                   3621: 
                   3622:        memset( s_pmnames, 0, sizeof( s_pmnames ) );
                   3623:        for ( i = 0; i < s_numplayermodels; i++ )
                   3624:        {
                   3625:                s_pmnames[i] = s_pmi[i].displayname;
                   3626:                if ( Q_stricmp( s_pmi[i].directory, currentdirectory ) == 0 )
                   3627:                {
                   3628:                        int j;
                   3629: 
                   3630:                        currentdirectoryindex = i;
                   3631: 
                   3632:                        for ( j = 0; j < s_pmi[i].nskins; j++ )
                   3633:                        {
                   3634:                                if ( Q_stricmp( s_pmi[i].skindisplaynames[j], currentskin ) == 0 )
                   3635:                                {
                   3636:                                        currentskinindex = j;
                   3637:                                        break;
                   3638:                                }
                   3639:                        }
                   3640:                }
                   3641:        }
                   3642: 
                   3643:        s_player_config_menu.x = viddef.width / 2 - 95; 
                   3644:        s_player_config_menu.y = viddef.height / 2 - 97;
                   3645:        s_player_config_menu.nitems = 0;
                   3646: 
                   3647:        s_player_name_field.generic.type = MTYPE_FIELD;
                   3648:        s_player_name_field.generic.name = "name";
                   3649:        s_player_name_field.generic.callback = 0;
                   3650:        s_player_name_field.generic.x           = 0;
                   3651:        s_player_name_field.generic.y           = 0;
                   3652:        s_player_name_field.length      = 20;
                   3653:        s_player_name_field.visible_length = 20;
                   3654:        strcpy( s_player_name_field.buffer, name->string );
                   3655:        s_player_name_field.cursor = strlen( name->string );
                   3656: 
                   3657:        s_player_model_title.generic.type = MTYPE_SEPARATOR;
                   3658:        s_player_model_title.generic.name = "model";
                   3659:        s_player_model_title.generic.x    = -8;
                   3660:        s_player_model_title.generic.y   = 60;
                   3661: 
                   3662:        s_player_model_box.generic.type = MTYPE_SPINCONTROL;
                   3663:        s_player_model_box.generic.x    = -56;
                   3664:        s_player_model_box.generic.y    = 70;
                   3665:        s_player_model_box.generic.callback = ModelCallback;
                   3666:        s_player_model_box.generic.cursor_offset = -48;
                   3667:        s_player_model_box.curvalue = currentdirectoryindex;
                   3668:        s_player_model_box.itemnames = s_pmnames;
                   3669: 
                   3670:        s_player_skin_title.generic.type = MTYPE_SEPARATOR;
                   3671:        s_player_skin_title.generic.name = "skin";
                   3672:        s_player_skin_title.generic.x    = -16;
                   3673:        s_player_skin_title.generic.y    = 84;
                   3674: 
                   3675:        s_player_skin_box.generic.type = MTYPE_SPINCONTROL;
                   3676:        s_player_skin_box.generic.x     = -56;
                   3677:        s_player_skin_box.generic.y     = 94;
                   3678:        s_player_skin_box.generic.name  = 0;
                   3679:        s_player_skin_box.generic.callback = 0;
                   3680:        s_player_skin_box.generic.cursor_offset = -48;
                   3681:        s_player_skin_box.curvalue = currentskinindex;
                   3682:        s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames;
                   3683: 
                   3684:        s_player_hand_title.generic.type = MTYPE_SEPARATOR;
                   3685:        s_player_hand_title.generic.name = "handedness";
                   3686:        s_player_hand_title.generic.x    = 32;
                   3687:        s_player_hand_title.generic.y    = 108;
                   3688: 
                   3689:        s_player_handedness_box.generic.type = MTYPE_SPINCONTROL;
                   3690:        s_player_handedness_box.generic.x       = -56;
                   3691:        s_player_handedness_box.generic.y       = 118;
                   3692:        s_player_handedness_box.generic.name    = 0;
                   3693:        s_player_handedness_box.generic.cursor_offset = -48;
                   3694:        s_player_handedness_box.generic.callback = HandednessCallback;
                   3695:        s_player_handedness_box.curvalue = Cvar_VariableValue( "hand" );
                   3696:        s_player_handedness_box.itemnames = handedness;
                   3697: 
1.1.1.2   root     3698:        for (i = 0; i < sizeof(rate_tbl) / sizeof(*rate_tbl) - 1; i++)
                   3699:                if (Cvar_VariableValue("rate") == rate_tbl[i])
                   3700:                        break;
                   3701: 
                   3702:        s_player_rate_title.generic.type = MTYPE_SEPARATOR;
                   3703:        s_player_rate_title.generic.name = "connect speed";
                   3704:        s_player_rate_title.generic.x    = 56;
                   3705:        s_player_rate_title.generic.y    = 156;
                   3706: 
                   3707:        s_player_rate_box.generic.type = MTYPE_SPINCONTROL;
                   3708:        s_player_rate_box.generic.x     = -56;
                   3709:        s_player_rate_box.generic.y     = 166;
                   3710:        s_player_rate_box.generic.name  = 0;
                   3711:        s_player_rate_box.generic.cursor_offset = -48;
                   3712:        s_player_rate_box.generic.callback = RateCallback;
                   3713:        s_player_rate_box.curvalue = i;
                   3714:        s_player_rate_box.itemnames = rate_names;
                   3715: 
                   3716:        s_player_download_action.generic.type = MTYPE_ACTION;
                   3717:        s_player_download_action.generic.name   = "download options";
                   3718:        s_player_download_action.generic.flags= QMF_LEFT_JUSTIFY;
                   3719:        s_player_download_action.generic.x      = -24;
                   3720:        s_player_download_action.generic.y      = 186;
                   3721:        s_player_download_action.generic.statusbar = NULL;
                   3722:        s_player_download_action.generic.callback = DownloadOptionsFunc;
                   3723: 
1.1       root     3724:        Menu_AddItem( &s_player_config_menu, &s_player_name_field );
                   3725:        Menu_AddItem( &s_player_config_menu, &s_player_model_title );
                   3726:        Menu_AddItem( &s_player_config_menu, &s_player_model_box );
                   3727:        if ( s_player_skin_box.itemnames )
                   3728:        {
                   3729:                Menu_AddItem( &s_player_config_menu, &s_player_skin_title );
                   3730:                Menu_AddItem( &s_player_config_menu, &s_player_skin_box );
                   3731:        }
                   3732:        Menu_AddItem( &s_player_config_menu, &s_player_hand_title );
                   3733:        Menu_AddItem( &s_player_config_menu, &s_player_handedness_box );
1.1.1.2   root     3734:        Menu_AddItem( &s_player_config_menu, &s_player_rate_title );
                   3735:        Menu_AddItem( &s_player_config_menu, &s_player_rate_box );
                   3736:        Menu_AddItem( &s_player_config_menu, &s_player_download_action );
                   3737: 
                   3738:        return true;
1.1       root     3739: }
                   3740: 
                   3741: void PlayerConfig_MenuDraw( void )
                   3742: {
                   3743:        extern float CalcFov( float fov_x, float w, float h );
                   3744:        refdef_t refdef;
                   3745:        char scratch[MAX_QPATH];
                   3746: 
                   3747:        memset( &refdef, 0, sizeof( refdef ) );
                   3748: 
                   3749:        refdef.x = viddef.width / 2;
                   3750:        refdef.y = viddef.height / 2 - 72;
                   3751:        refdef.width = 144;
                   3752:        refdef.height = 168;
                   3753:        refdef.fov_x = 40;
                   3754:        refdef.fov_y = CalcFov( refdef.fov_x, refdef.width, refdef.height );
                   3755:        refdef.time = cls.realtime*0.001;
                   3756: 
                   3757:        if ( s_pmi[s_player_model_box.curvalue].skindisplaynames )
                   3758:        {
                   3759:                static int yaw;
                   3760:                int maxframe = 29;
                   3761:                entity_t entity;
                   3762: 
                   3763:                memset( &entity, 0, sizeof( entity ) );
                   3764: 
                   3765:                Com_sprintf( scratch, sizeof( scratch ), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory );
                   3766:                entity.model = re.RegisterModel( scratch );
                   3767:                Com_sprintf( scratch, sizeof( scratch ), "players/%s/%s.pcx", s_pmi[s_player_model_box.curvalue].directory, s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
                   3768:                entity.skin = re.RegisterSkin( scratch );
                   3769:                entity.flags = RF_FULLBRIGHT;
                   3770:                entity.origin[0] = 80;
                   3771:                entity.origin[1] = 0;
                   3772:                entity.origin[2] = 0;
                   3773:                VectorCopy( entity.origin, entity.oldorigin );
                   3774:                entity.frame = 0;
                   3775:                entity.oldframe = 0;
                   3776:                entity.backlerp = 0.0;
                   3777:                entity.angles[1] = yaw++;
                   3778:                if ( ++yaw > 360 )
                   3779:                        yaw -= 360;
                   3780: 
                   3781:                refdef.areabits = 0;
                   3782:                refdef.num_entities = 1;
                   3783:                refdef.entities = &entity;
                   3784:                refdef.lightstyles = 0;
                   3785:                refdef.rdflags = RDF_NOWORLDMODEL;
                   3786: 
                   3787:                Menu_Draw( &s_player_config_menu );
                   3788: 
                   3789:                M_DrawTextBox( ( refdef.x ) * ( 320.0F / viddef.width ) - 8, ( viddef.height / 2 ) * ( 240.0F / viddef.height) - 77, refdef.width / 8, refdef.height / 8 );
                   3790:                refdef.height += 4;
                   3791: 
                   3792:                re.RenderFrame( &refdef );
                   3793: 
                   3794:                Com_sprintf( scratch, sizeof( scratch ), "/players/%s/%s_i.pcx", 
                   3795:                        s_pmi[s_player_model_box.curvalue].directory,
                   3796:                        s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
                   3797:                re.DrawPic( s_player_config_menu.x - 40, refdef.y, scratch );
                   3798:        }
                   3799: }
1.1.1.2   root     3800: 
1.1       root     3801: const char *PlayerConfig_MenuKey (int key)
                   3802: {
                   3803:        int i;
                   3804: 
                   3805:        if ( key == K_ESCAPE )
                   3806:        {
                   3807:                char scratch[1024];
                   3808: 
                   3809:                Cvar_Set( "name", s_player_name_field.buffer );
                   3810: 
                   3811:                Com_sprintf( scratch, sizeof( scratch ), "%s/%s", 
                   3812:                        s_pmi[s_player_model_box.curvalue].directory, 
1.1.1.3 ! root     3813:                        s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
1.1       root     3814: 
                   3815:                Cvar_Set( "skin", scratch );
                   3816: 
                   3817:                for ( i = 0; i < s_numplayermodels; i++ )
                   3818:                {
                   3819:                        int j;
                   3820: 
                   3821:                        for ( j = 0; j < s_pmi[i].nskins; j++ )
                   3822:                        {
                   3823:                                if ( s_pmi[i].skindisplaynames[j] )
                   3824:                                        free( s_pmi[i].skindisplaynames[j] );
                   3825:                                s_pmi[i].skindisplaynames[j] = 0;
                   3826:                        }
                   3827:                        free( s_pmi[i].skindisplaynames );
                   3828:                        s_pmi[i].skindisplaynames = 0;
                   3829:                        s_pmi[i].nskins = 0;
                   3830:                }
                   3831:        }
                   3832:        return Default_MenuKey( &s_player_config_menu, key );
                   3833: }
1.1.1.2   root     3834: 
                   3835: 
1.1       root     3836: void M_Menu_PlayerConfig_f (void)
                   3837: {
1.1.1.2   root     3838:        if (!PlayerConfig_MenuInit())
                   3839:        {
                   3840:                Menu_SetStatusBar( &s_multiplayer_menu, "No valid player models found" );
                   3841:                return;
                   3842:        }
                   3843:        Menu_SetStatusBar( &s_multiplayer_menu, NULL );
1.1       root     3844:        M_PushMenu( PlayerConfig_MenuDraw, PlayerConfig_MenuKey );
                   3845: }
1.1.1.2   root     3846: 
                   3847: 
1.1       root     3848: /*
                   3849: =======================================================================
                   3850: 
                   3851: GALLERY MENU
                   3852: 
                   3853: =======================================================================
                   3854: */
                   3855: #if 0
                   3856: void M_Menu_Gallery_f( void )
                   3857: {
                   3858:        extern void Gallery_MenuDraw( void );
                   3859:        extern const char *Gallery_MenuKey( int key );
1.1.1.2   root     3860: 
1.1       root     3861:        M_PushMenu( Gallery_MenuDraw, Gallery_MenuKey );
                   3862: }
                   3863: #endif
1.1.1.2   root     3864: 
1.1       root     3865: /*
                   3866: =======================================================================
1.1.1.2   root     3867: 
1.1       root     3868: QUIT MENU
1.1.1.2   root     3869: 
1.1       root     3870: =======================================================================
                   3871: */
1.1.1.2   root     3872: 
1.1       root     3873: const char *M_Quit_Key (int key)
                   3874: {
                   3875:        switch (key)
                   3876:        {
                   3877:        case K_ESCAPE:
                   3878:        case 'n':
                   3879:        case 'N':
                   3880:                M_PopMenu ();
                   3881:                break;
1.1.1.2   root     3882: 
1.1       root     3883:        case 'Y':
                   3884:        case 'y':
                   3885:                cls.key_dest = key_console;
                   3886:                CL_Quit_f ();
                   3887:                break;
1.1.1.2   root     3888: 
1.1       root     3889:        default:
                   3890:                break;
                   3891:        }
1.1.1.2   root     3892: 
1.1       root     3893:        return NULL;
1.1.1.2   root     3894: 
1.1       root     3895: }
1.1.1.2   root     3896: 
                   3897: 
1.1       root     3898: void M_Quit_Draw (void)
                   3899: {
                   3900:        int             w, h;
1.1.1.2   root     3901: 
1.1       root     3902:        re.DrawGetPicSize (&w, &h, "quit");
                   3903:        re.DrawPic ( (viddef.width-w)/2, (viddef.height-h)/2, "quit");
                   3904: }
1.1.1.2   root     3905: 
                   3906: 
1.1       root     3907: void M_Menu_Quit_f (void)
                   3908: {
                   3909:        M_PushMenu (M_Quit_Draw, M_Quit_Key);
                   3910: }
1.1.1.2   root     3911: 
                   3912: 
                   3913: 
1.1       root     3914: //=============================================================================
                   3915: /* Menu Subsystem */
1.1.1.2   root     3916: 
                   3917: 
1.1       root     3918: /*
                   3919: =================
                   3920: M_Init
                   3921: =================
                   3922: */
                   3923: void M_Init (void)
                   3924: {
                   3925:        Cmd_AddCommand ("menu_main", M_Menu_Main_f);
                   3926:        Cmd_AddCommand ("menu_game", M_Menu_Game_f);
                   3927:                Cmd_AddCommand ("menu_loadgame", M_Menu_LoadGame_f);
                   3928:                Cmd_AddCommand ("menu_savegame", M_Menu_SaveGame_f);
                   3929:                Cmd_AddCommand ("menu_joinserver", M_Menu_JoinServer_f);
                   3930:                        Cmd_AddCommand ("menu_addressbook", M_Menu_AddressBook_f);
                   3931:                Cmd_AddCommand ("menu_startserver", M_Menu_StartServer_f);
                   3932:                        Cmd_AddCommand ("menu_dmoptions", M_Menu_DMOptions_f);
                   3933:                Cmd_AddCommand ("menu_playerconfig", M_Menu_PlayerConfig_f);
1.1.1.2   root     3934:                        Cmd_AddCommand ("menu_downloadoptions", M_Menu_DownloadOptions_f);
1.1       root     3935:                Cmd_AddCommand ("menu_credits", M_Menu_Credits_f );
                   3936:        Cmd_AddCommand ("menu_multiplayer", M_Menu_Multiplayer_f );
                   3937:        Cmd_AddCommand ("menu_video", M_Menu_Video_f);
                   3938:        Cmd_AddCommand ("menu_options", M_Menu_Options_f);
                   3939:                Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
                   3940:        Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
                   3941: }
1.1.1.2   root     3942: 
                   3943: 
1.1       root     3944: /*
                   3945: =================
                   3946: M_Draw
                   3947: =================
                   3948: */
                   3949: void M_Draw (void)
                   3950: {
                   3951:        if (cls.key_dest != key_menu)
                   3952:                return;
1.1.1.2   root     3953: 
1.1       root     3954:        // repaint everything next frame
                   3955:        SCR_DirtyScreen ();
1.1.1.2   root     3956: 
1.1       root     3957:        // dim everything behind it down
                   3958:        if (cl.cinematictime > 0)
                   3959:                re.DrawFill (0,0,viddef.width, viddef.height, 0);
                   3960:        else
                   3961:                re.DrawFadeScreen ();
1.1.1.2   root     3962: 
1.1       root     3963:        m_drawfunc ();
1.1.1.2   root     3964: 
1.1       root     3965:        // delay playing the enter sound until after the
                   3966:        // menu has been drawn, to avoid delay while
                   3967:        // caching images
                   3968:        if (m_entersound)
                   3969:        {
                   3970:                S_StartLocalSound( menu_in_sound );
                   3971:                m_entersound = false;
                   3972:        }
                   3973: }
1.1.1.2   root     3974: 
                   3975: 
1.1       root     3976: /*
                   3977: =================
                   3978: M_Keydown
                   3979: =================
                   3980: */
                   3981: void M_Keydown (int key)
                   3982: {
                   3983:        const char *s;
1.1.1.2   root     3984: 
1.1       root     3985:        if (m_keyfunc)
                   3986:                if ( ( s = m_keyfunc( key ) ) != 0 )
                   3987:                        S_StartLocalSound( ( char * ) s );
                   3988: }
1.1.1.2   root     3989: 
                   3990: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.